From 08bb5cbcbff6e1b42fa1715224aa989cd308b073 Mon Sep 17 00:00:00 2001 From: Shivam Date: Sat, 16 May 2020 02:57:58 +0200 Subject: [PATCH 01/59] Introduce model to store path of stable osu! --- osu.Game.Tournament/Models/StableInfo.cs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 osu.Game.Tournament/Models/StableInfo.cs diff --git a/osu.Game.Tournament/Models/StableInfo.cs b/osu.Game.Tournament/Models/StableInfo.cs new file mode 100644 index 0000000000..b89160536d --- /dev/null +++ b/osu.Game.Tournament/Models/StableInfo.cs @@ -0,0 +1,17 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using osu.Framework.Bindables; + +namespace osu.Game.Tournament.Models +{ + /// + /// Holds the complete data required to operate the tournament system. + /// + [Serializable] + public class StableInfo + { + public Bindable StablePath = new Bindable(string.Empty); + } +} From c40b3b905313a78ee229bdd49589d26c32f27bfd Mon Sep 17 00:00:00 2001 From: Shivam Date: Sat, 16 May 2020 02:59:48 +0200 Subject: [PATCH 02/59] Refactored stable path finding and added json config detection. This also migrates the values found in the other methods to the configuration file. --- osu.Game.Tournament/IPC/FileBasedIPC.cs | 173 ++++++++++++++++++------ 1 file changed, 135 insertions(+), 38 deletions(-) diff --git a/osu.Game.Tournament/IPC/FileBasedIPC.cs b/osu.Game.Tournament/IPC/FileBasedIPC.cs index 53ba597a7e..321a4ad0aa 100644 --- a/osu.Game.Tournament/IPC/FileBasedIPC.cs +++ b/osu.Game.Tournament/IPC/FileBasedIPC.cs @@ -4,6 +4,8 @@ using System; using System.IO; using System.Linq; +using System.Collections.Generic; +using Newtonsoft.Json; using Microsoft.Win32; using osu.Framework.Allocation; using osu.Framework.Logging; @@ -35,7 +37,15 @@ namespace osu.Game.Tournament.IPC private int lastBeatmapId; private ScheduledDelegate scheduled; - public Storage Storage { get; private set; } + [Resolved] + private StableInfo stableInfo { get; set; } + + private const string stable_config = "tournament/stable.json"; + + public Storage IPCStorage { get; private set; } + + [Resolved] + private Storage tournamentStorage { get; set; } [BackgroundDependencyLoader] private void load() @@ -47,7 +57,7 @@ namespace osu.Game.Tournament.IPC { scheduled?.Cancel(); - Storage = null; + IPCStorage = null; try { @@ -56,20 +66,20 @@ namespace osu.Game.Tournament.IPC if (string.IsNullOrEmpty(path)) return null; - Storage = new DesktopStorage(path, host as DesktopGameHost); + IPCStorage = new DesktopStorage(path, host as DesktopGameHost); const string file_ipc_filename = "ipc.txt"; const string file_ipc_state_filename = "ipc-state.txt"; const string file_ipc_scores_filename = "ipc-scores.txt"; const string file_ipc_channel_filename = "ipc-channel.txt"; - if (Storage.Exists(file_ipc_filename)) + if (IPCStorage.Exists(file_ipc_filename)) { scheduled = Scheduler.AddDelayed(delegate { try { - using (var stream = Storage.GetStream(file_ipc_filename)) + using (var stream = IPCStorage.GetStream(file_ipc_filename)) using (var sr = new StreamReader(stream)) { var beatmapId = int.Parse(sr.ReadLine()); @@ -101,7 +111,7 @@ namespace osu.Game.Tournament.IPC try { - using (var stream = Storage.GetStream(file_ipc_channel_filename)) + using (var stream = IPCStorage.GetStream(file_ipc_channel_filename)) using (var sr = new StreamReader(stream)) { ChatChannel.Value = sr.ReadLine(); @@ -114,7 +124,7 @@ namespace osu.Game.Tournament.IPC try { - using (var stream = Storage.GetStream(file_ipc_state_filename)) + using (var stream = IPCStorage.GetStream(file_ipc_state_filename)) using (var sr = new StreamReader(stream)) { State.Value = (TourneyState)Enum.Parse(typeof(TourneyState), sr.ReadLine()); @@ -127,7 +137,7 @@ namespace osu.Game.Tournament.IPC try { - using (var stream = Storage.GetStream(file_ipc_scores_filename)) + using (var stream = IPCStorage.GetStream(file_ipc_scores_filename)) using (var sr = new StreamReader(stream)) { Score1.Value = int.Parse(sr.ReadLine()); @@ -146,54 +156,141 @@ namespace osu.Game.Tournament.IPC Logger.Error(e, "Stable installation could not be found; disabling file based IPC"); } - return Storage; + return IPCStorage; } + private static bool checkExists(string p) => File.Exists(Path.Combine(p, "ipc.txt")); + private string findStablePath() { - static bool checkExists(string p) => File.Exists(Path.Combine(p, "ipc.txt")); - string stableInstallPath = string.Empty; try { - try + List> stableFindMethods = new List> { - stableInstallPath = Environment.GetEnvironmentVariable("OSU_STABLE_PATH"); + findFromJsonConfig, + findFromEnvVar, + findFromRegistry, + findFromLocalAppData, + findFromDotFolder + }; - if (checkExists(stableInstallPath)) + foreach (var r in stableFindMethods) + { + stableInstallPath = r.Invoke(); + + if (stableInstallPath != null) + { return stableInstallPath; - } - catch - { + } } - try - { - using (RegistryKey key = Registry.ClassesRoot.OpenSubKey("osu")) - stableInstallPath = key?.OpenSubKey(@"shell\open\command")?.GetValue(string.Empty).ToString().Split('"')[1].Replace("osu!.exe", ""); - - if (checkExists(stableInstallPath)) - return stableInstallPath; - } - catch - { - } - - stableInstallPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), @"osu!"); - if (checkExists(stableInstallPath)) - return stableInstallPath; - - stableInstallPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".osu"); - if (checkExists(stableInstallPath)) - return stableInstallPath; - - return null; + return stableInstallPath; } finally { Logger.Log($"Stable path for tourney usage: {stableInstallPath}"); } } + + private void saveStablePath() + { + using (var stream = tournamentStorage.GetStream(stable_config, FileAccess.Write, FileMode.Create)) + using (var sw = new StreamWriter(stream)) + { + sw.Write(JsonConvert.SerializeObject(stableInfo, + new JsonSerializerSettings + { + Formatting = Formatting.Indented, + NullValueHandling = NullValueHandling.Ignore, + DefaultValueHandling = DefaultValueHandling.Ignore, + })); + } + } + + private string findFromEnvVar() + { + try + { + Logger.Log("Trying to find stable with environment variables"); + string stableInstallPath = Environment.GetEnvironmentVariable("OSU_STABLE_PATH"); + + if (checkExists(stableInstallPath)) + { + stableInfo.StablePath.Value = stableInstallPath; + saveStablePath(); + return stableInstallPath; + } + } + catch + { + } + + return null; + } + + private string findFromJsonConfig() + { + try + { + Logger.Log("Trying to find stable through the json config"); + return stableInfo.StablePath.Value; + } + catch + { + } + + return null; + } + + private string findFromLocalAppData() + { + Logger.Log("Trying to find stable in %LOCALAPPDATA%"); + string stableInstallPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), @"osu!"); + + if (checkExists(stableInstallPath)) + { + stableInfo.StablePath.Value = stableInstallPath; + saveStablePath(); + return stableInstallPath; + } + + return null; + } + + private string findFromDotFolder() + { + Logger.Log("Trying to find stable in dotfolders"); + string stableInstallPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".osu"); + + if (checkExists(stableInstallPath)) + { + stableInfo.StablePath.Value = stableInstallPath; + saveStablePath(); + return stableInstallPath; + } + + return null; + } + + private string findFromRegistry() + { + Logger.Log("Trying to find stable in registry"); + + string stableInstallPath; + + using (RegistryKey key = Registry.ClassesRoot.OpenSubKey("osu")) + stableInstallPath = key?.OpenSubKey(@"shell\open\command")?.GetValue(string.Empty).ToString().Split('"')[1].Replace("osu!.exe", ""); + + if (checkExists(stableInstallPath)) + { + stableInfo.StablePath.Value = stableInstallPath; + saveStablePath(); + return stableInstallPath; + } + + return null; + } } } From 9944a514da95181dd6c4be222b2bd5d3e069dee4 Mon Sep 17 00:00:00 2001 From: Shivam Date: Sat, 16 May 2020 03:00:37 +0200 Subject: [PATCH 03/59] Dependency cache the ipc location file --- osu.Game.Tournament/TournamentGameBase.cs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index 85db9e61fb..31c56c7fc4 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -33,6 +33,8 @@ namespace osu.Game.Tournament { private const string bracket_filename = "bracket.json"; + private const string stable_config = "tournament/stable.json"; + private LadderInfo ladder; private Storage storage; @@ -43,6 +45,7 @@ namespace osu.Game.Tournament private Bindable windowSize; private FileBasedIPC ipc; + private StableInfo stableInfo; private Drawable heightWarning; @@ -71,6 +74,7 @@ namespace osu.Game.Tournament }), true); readBracket(); + readStableConfig(); ladder.CurrentMatch.Value = ladder.Matches.FirstOrDefault(p => p.Current.Value); @@ -141,6 +145,23 @@ namespace osu.Game.Tournament }); } + private void readStableConfig() + { + if (storage.Exists(stable_config)) + { + using (Stream stream = storage.GetStream(stable_config, FileAccess.Read, FileMode.Open)) + using (var sr = new StreamReader(stream)) + { + stableInfo = JsonConvert.DeserializeObject(sr.ReadToEnd()); + } + } + + if (stableInfo == null) + stableInfo = new StableInfo(); + + dependencies.Cache(stableInfo); + } + private void readBracket() { if (storage.Exists(bracket_filename)) From 3fc888ef95f62154cf1e32aa178036926da550cb Mon Sep 17 00:00:00 2001 From: Shivam Date: Sat, 16 May 2020 03:03:10 +0200 Subject: [PATCH 04/59] User interface setup for custom IPC location Right now makes use of another ActionableInfo field. Probably a better idea to add an extra button to the Current IPC Storage actionable field. --- .../Components/IPCNotFoundDialog.cs | 27 ++++ osu.Game.Tournament/Screens/SetupScreen.cs | 34 +++- .../Screens/StablePathSelectScreen.cs | 149 ++++++++++++++++++ 3 files changed, 207 insertions(+), 3 deletions(-) create mode 100644 osu.Game.Tournament/Components/IPCNotFoundDialog.cs create mode 100644 osu.Game.Tournament/Screens/StablePathSelectScreen.cs diff --git a/osu.Game.Tournament/Components/IPCNotFoundDialog.cs b/osu.Game.Tournament/Components/IPCNotFoundDialog.cs new file mode 100644 index 0000000000..d4f9edc182 --- /dev/null +++ b/osu.Game.Tournament/Components/IPCNotFoundDialog.cs @@ -0,0 +1,27 @@ +// 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.Graphics.Sprites; +using osu.Game.Overlays.Dialog; + +namespace osu.Game.Tournament.Components +{ + public class IPCNotFoundDialog : PopupDialog + { + public IPCNotFoundDialog() + { + BodyText = "Select a directory that contains an osu! Cutting Edge installation"; + + Icon = FontAwesome.Regular.Angry; + HeaderText = @"This is an invalid IPC Directory!"; + Buttons = new PopupDialogButton[] + { + new PopupDialogOkButton + { + Text = @"Alright.", + Action = () => { Expire(); } + } + }; + } + } +} diff --git a/osu.Game.Tournament/Screens/SetupScreen.cs b/osu.Game.Tournament/Screens/SetupScreen.cs index c91379b2d6..93edd73ff8 100644 --- a/osu.Game.Tournament/Screens/SetupScreen.cs +++ b/osu.Game.Tournament/Screens/SetupScreen.cs @@ -15,6 +15,8 @@ using osu.Game.Online.API; using osu.Game.Overlays; using osu.Game.Rulesets; using osu.Game.Tournament.IPC; +using osu.Framework.Platform; +using osu.Game.Tournament.Models; using osuTK; using osuTK.Graphics; @@ -26,6 +28,7 @@ namespace osu.Game.Tournament.Screens private LoginOverlay loginOverlay; private ActionableInfo resolution; + private const string stable_config = "tournament/stable.json"; [Resolved] private MatchIPCInfo ipc { get; set; } @@ -36,8 +39,17 @@ namespace osu.Game.Tournament.Screens [Resolved] private RulesetStore rulesets { get; set; } + [Resolved(canBeNull: true)] + private TournamentSceneManager sceneManager { get; set; } + private Bindable windowSize; + [Resolved] + private Storage storage { get; set; } + + [Resolved] + private StableInfo stableInfo { get; set; } + [BackgroundDependencyLoader] private void load(FrameworkConfigManager frameworkConfig) { @@ -62,7 +74,6 @@ namespace osu.Game.Tournament.Screens private void reload() { var fileBasedIpc = ipc as FileBasedIPC; - fillFlow.Children = new Drawable[] { new ActionableInfo @@ -74,11 +85,28 @@ namespace osu.Game.Tournament.Screens fileBasedIpc?.LocateStableStorage(); reload(); }, - Value = fileBasedIpc?.Storage?.GetFullPath(string.Empty) ?? "Not found", - Failing = fileBasedIpc?.Storage == null, + Value = fileBasedIpc?.IPCStorage?.GetFullPath(string.Empty) ?? "Not found", + Failing = fileBasedIpc?.IPCStorage == null, Description = "The osu!stable installation which is currently being used as a data source. If a source is not found, make sure you have created an empty ipc.txt in your stable cutting-edge installation, and that it is registered as the default osu! install." }, new ActionableInfo + { + Label = "Custom IPC source", + ButtonText = "Change path", + Action = () => + { + stableInfo.StablePath.BindValueChanged(_ => + { + fileBasedIpc?.LocateStableStorage(); + Schedule(reload); + }); + sceneManager.SetScreen(new StablePathSelectScreen()); + }, + Value = fileBasedIpc?.IPCStorage?.GetFullPath(string.Empty) ?? "Not found", + Failing = fileBasedIpc?.IPCStorage == null, + Description = "The osu!stable installation which is currently being used as a data source. If a source is not found, you can manually select the desired osu! installation that you want to use." + }, + new ActionableInfo { Label = "Current User", ButtonText = "Change Login", diff --git a/osu.Game.Tournament/Screens/StablePathSelectScreen.cs b/osu.Game.Tournament/Screens/StablePathSelectScreen.cs new file mode 100644 index 0000000000..1faacc727f --- /dev/null +++ b/osu.Game.Tournament/Screens/StablePathSelectScreen.cs @@ -0,0 +1,149 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.IO; +using Newtonsoft.Json; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Logging; +using osu.Framework.Platform; +using osu.Game.Tournament.Models; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; +using osu.Game.Graphics.UserInterfaceV2; +using osu.Game.Overlays; +using osu.Game.Tournament.IPC; +using osu.Game.Tournament.Components; +using osuTK; + +namespace osu.Game.Tournament.Screens +{ + public class StablePathSelectScreen : TournamentScreen + { + private DirectorySelector directorySelector; + + private const string stable_config = "tournament/stable.json"; + + [Resolved] + private StableInfo stableInfo { get; set; } + + [Resolved] + private MatchIPCInfo ipc { get; set; } + + private DialogOverlay overlay; + + [Resolved(canBeNull: true)] + private TournamentSceneManager sceneManager { get; set; } + + [BackgroundDependencyLoader(true)] + private void load(Storage storage, OsuColour colours) + { + // begin selection in the parent directory of the current storage location + var initialPath = new DirectoryInfo(stableInfo.StablePath.Value).FullName; + + AddInternal(new Container + { + Masking = true, + CornerRadius = 10, + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(0.5f, 0.8f), + Children = new Drawable[] + { + new Box + { + Colour = colours.GreySeafoamDark, + RelativeSizeAxes = Axes.Both, + }, + new GridContainer + { + RelativeSizeAxes = Axes.Both, + RowDimensions = new[] + { + new Dimension(), + new Dimension(GridSizeMode.Relative, 0.8f), + new Dimension(), + }, + Content = new[] + { + new Drawable[] + { + new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Text = "Please select a new location", + Font = OsuFont.Default.With(size: 40) + }, + }, + new Drawable[] + { + directorySelector = new DirectorySelector(initialPath) + { + RelativeSizeAxes = Axes.Both, + } + }, + new Drawable[] + { + new TriangleButton + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Width = 300, + Text = "Select stable path", + Action = () => { start(storage); } + }, + } + } + } + } + }); + } + + private static bool checkExists(string p) => File.Exists(Path.Combine(p, "ipc.txt")); + + private void start(Storage storage) + { + var target = directorySelector.CurrentDirectory.Value.FullName; + + if (checkExists(target)) + { + stableInfo.StablePath.Value = target; + + try + { + using (var stream = storage.GetStream(stable_config, FileAccess.Write, FileMode.Create)) + using (var sw = new StreamWriter(stream)) + { + sw.Write(JsonConvert.SerializeObject(stableInfo, + new JsonSerializerSettings + { + Formatting = Formatting.Indented, + NullValueHandling = NullValueHandling.Ignore, + DefaultValueHandling = DefaultValueHandling.Ignore, + })); + } + + sceneManager?.SetScreen(typeof(SetupScreen)); + } + catch (Exception e) + { + Logger.Log($"Error during migration: {e.Message}", level: LogLevel.Error); + } + } + else + { + overlay = new DialogOverlay(); + overlay.Push(new IPCNotFoundDialog()); + AddInternal(overlay); + Logger.Log("Folder is not an osu! stable CE directory"); + // Return an error in the picker that the directory does not contain ipc.txt + } + } + } +} From 80d188ec91caa05af9c71854a25b8d543aae7f05 Mon Sep 17 00:00:00 2001 From: Shivam Date: Sun, 17 May 2020 22:26:42 +0200 Subject: [PATCH 05/59] Update xmldoc with accurate information about the model --- osu.Game.Tournament/Models/StableInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tournament/Models/StableInfo.cs b/osu.Game.Tournament/Models/StableInfo.cs index b89160536d..4818842151 100644 --- a/osu.Game.Tournament/Models/StableInfo.cs +++ b/osu.Game.Tournament/Models/StableInfo.cs @@ -7,7 +7,7 @@ using osu.Framework.Bindables; namespace osu.Game.Tournament.Models { /// - /// Holds the complete data required to operate the tournament system. + /// Holds the path to locate the osu! stable cutting-edge installation. /// [Serializable] public class StableInfo From 4bc858a2159bc2c73033800a48381831f7a42276 Mon Sep 17 00:00:00 2001 From: Shivam Date: Sun, 17 May 2020 22:27:44 +0200 Subject: [PATCH 06/59] Force a read of the location file during detection --- osu.Game.Tournament/IPC/FileBasedIPC.cs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/osu.Game.Tournament/IPC/FileBasedIPC.cs b/osu.Game.Tournament/IPC/FileBasedIPC.cs index 321a4ad0aa..0454ef4e41 100644 --- a/osu.Game.Tournament/IPC/FileBasedIPC.cs +++ b/osu.Game.Tournament/IPC/FileBasedIPC.cs @@ -232,15 +232,17 @@ namespace osu.Game.Tournament.IPC private string findFromJsonConfig() { - try + Logger.Log("Trying to find stable through the json config"); + if (tournamentStorage.Exists(stable_config)) { - Logger.Log("Trying to find stable through the json config"); - return stableInfo.StablePath.Value; + using (Stream stream = tournamentStorage.GetStream(stable_config, FileAccess.Read, FileMode.Open)) + using (var sr = new StreamReader(stream)) + { + stableInfo = JsonConvert.DeserializeObject(sr.ReadToEnd()); + return stableInfo.StablePath.Value; + } } - catch - { - } - + return null; } From fbbf51851ecad9f379d410cb60594d1ee81310e8 Mon Sep 17 00:00:00 2001 From: Shivam Date: Sun, 17 May 2020 22:28:24 +0200 Subject: [PATCH 07/59] Moved refresh button to directoryselector --- .../Screens/StablePathSelectScreen.cs | 145 ++++++++++++------ 1 file changed, 97 insertions(+), 48 deletions(-) diff --git a/osu.Game.Tournament/Screens/StablePathSelectScreen.cs b/osu.Game.Tournament/Screens/StablePathSelectScreen.cs index 1faacc727f..8b75bd9290 100644 --- a/osu.Game.Tournament/Screens/StablePathSelectScreen.cs +++ b/osu.Game.Tournament/Screens/StablePathSelectScreen.cs @@ -43,75 +43,107 @@ namespace osu.Game.Tournament.Screens private void load(Storage storage, OsuColour colours) { // begin selection in the parent directory of the current storage location - var initialPath = new DirectoryInfo(stableInfo.StablePath.Value).FullName; + var initialPath = new DirectoryInfo(storage.GetFullPath(string.Empty)).Parent?.FullName; - AddInternal(new Container + if (!string.IsNullOrEmpty(stableInfo.StablePath.Value)) { - Masking = true, - CornerRadius = 10, - RelativeSizeAxes = Axes.Both, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Size = new Vector2(0.5f, 0.8f), - Children = new Drawable[] + // If the original path info for osu! stable is not empty, set it to the parent directory of that location + initialPath = new DirectoryInfo(stableInfo.StablePath.Value).Parent?.FullName; + } + + AddRangeInternal(new Drawable[] + { + new Container { - new Box + Masking = true, + CornerRadius = 10, + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(0.5f, 0.8f), + Children = new Drawable[] { - Colour = colours.GreySeafoamDark, - RelativeSizeAxes = Axes.Both, - }, - new GridContainer - { - RelativeSizeAxes = Axes.Both, - RowDimensions = new[] + new Box { - new Dimension(), - new Dimension(GridSizeMode.Relative, 0.8f), - new Dimension(), + Colour = colours.GreySeafoamDark, + RelativeSizeAxes = Axes.Both, }, - Content = new[] + new GridContainer { - new Drawable[] + RelativeSizeAxes = Axes.Both, + RowDimensions = new[] { - new OsuSpriteText - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Text = "Please select a new location", - Font = OsuFont.Default.With(size: 40) - }, + new Dimension(), + new Dimension(GridSizeMode.Relative, 0.8f), + new Dimension(), }, - new Drawable[] + Content = new[] { - directorySelector = new DirectorySelector(initialPath) + new Drawable[] { - RelativeSizeAxes = Axes.Both, + new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Text = "Please select a new location", + Font = OsuFont.Default.With(size: 40) + }, + }, + new Drawable[] + { + directorySelector = new DirectorySelector(initialPath) + { + RelativeSizeAxes = Axes.Both, + } + }, + new Drawable[] + { + new FillFlowContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(20), + Children = new Drawable[] + { + new TriangleButton + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Width = 300, + Text = "Select stable path", + Action = () => changePath(storage) + }, + new TriangleButton + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Width = 300, + Text = "Auto detect", + Action = autoDetect + }, + } + } } - }, - new Drawable[] - { - new TriangleButton - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Width = 300, - Text = "Select stable path", - Action = () => { start(storage); } - }, } } - } + }, + }, + new BackButton + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + State = { Value = Visibility.Visible }, + Action = () => sceneManager?.SetScreen(typeof(SetupScreen)) } }); } - private static bool checkExists(string p) => File.Exists(Path.Combine(p, "ipc.txt")); - - private void start(Storage storage) + private void changePath(Storage storage) { var target = directorySelector.CurrentDirectory.Value.FullName; - if (checkExists(target)) + if (File.Exists(Path.Combine(target, "ipc.txt"))) { stableInfo.StablePath.Value = target; @@ -145,5 +177,22 @@ namespace osu.Game.Tournament.Screens // Return an error in the picker that the directory does not contain ipc.txt } } + + private void autoDetect() + { + var fileBasedIpc = ipc as FileBasedIPC; + fileBasedIpc?.LocateStableStorage(); + if (fileBasedIpc?.IPCStorage == null) + { + // Could not auto detect + overlay = new DialogOverlay(); + overlay.Push(new IPCNotFoundDialog()); + AddInternal(overlay); + } + else + { + sceneManager?.SetScreen(typeof(SetupScreen)); + } + } } } From a97100216ca3da33c3aba2b91971d6baf3eb24df Mon Sep 17 00:00:00 2001 From: Shivam Date: Sun, 17 May 2020 22:28:54 +0200 Subject: [PATCH 08/59] Changed behaviour of refresh button in SetupScreen --- osu.Game.Tournament/Screens/SetupScreen.cs | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/osu.Game.Tournament/Screens/SetupScreen.cs b/osu.Game.Tournament/Screens/SetupScreen.cs index 93edd73ff8..dcaadc8247 100644 --- a/osu.Game.Tournament/Screens/SetupScreen.cs +++ b/osu.Game.Tournament/Screens/SetupScreen.cs @@ -82,20 +82,7 @@ namespace osu.Game.Tournament.Screens ButtonText = "Refresh", Action = () => { - fileBasedIpc?.LocateStableStorage(); - reload(); - }, - Value = fileBasedIpc?.IPCStorage?.GetFullPath(string.Empty) ?? "Not found", - Failing = fileBasedIpc?.IPCStorage == null, - Description = "The osu!stable installation which is currently being used as a data source. If a source is not found, make sure you have created an empty ipc.txt in your stable cutting-edge installation, and that it is registered as the default osu! install." - }, - new ActionableInfo - { - Label = "Custom IPC source", - ButtonText = "Change path", - Action = () => - { - stableInfo.StablePath.BindValueChanged(_ => + stableInfo.StablePath.BindValueChanged(_ => { fileBasedIpc?.LocateStableStorage(); Schedule(reload); @@ -104,7 +91,7 @@ namespace osu.Game.Tournament.Screens }, Value = fileBasedIpc?.IPCStorage?.GetFullPath(string.Empty) ?? "Not found", Failing = fileBasedIpc?.IPCStorage == null, - Description = "The osu!stable installation which is currently being used as a data source. If a source is not found, you can manually select the desired osu! installation that you want to use." + Description = "The osu!stable installation which is currently being used as a data source. If a source is not found, make sure you have created an empty ipc.txt in your stable cutting-edge installation." }, new ActionableInfo { From 59b006f9ac8688b75fa6556fb286f27f37cdbbca Mon Sep 17 00:00:00 2001 From: Shivam Date: Sun, 17 May 2020 22:46:43 +0200 Subject: [PATCH 09/59] Make IPC error dialog reusable and inspectcode fixes --- .../{IPCNotFoundDialog.cs => IPCErrorDialog.cs} | 11 +++++------ osu.Game.Tournament/IPC/FileBasedIPC.cs | 3 ++- osu.Game.Tournament/Screens/SetupScreen.cs | 2 +- osu.Game.Tournament/Screens/StablePathSelectScreen.cs | 5 +++-- 4 files changed, 11 insertions(+), 10 deletions(-) rename osu.Game.Tournament/Components/{IPCNotFoundDialog.cs => IPCErrorDialog.cs} (65%) diff --git a/osu.Game.Tournament/Components/IPCNotFoundDialog.cs b/osu.Game.Tournament/Components/IPCErrorDialog.cs similarity index 65% rename from osu.Game.Tournament/Components/IPCNotFoundDialog.cs rename to osu.Game.Tournament/Components/IPCErrorDialog.cs index d4f9edc182..07fd0ac973 100644 --- a/osu.Game.Tournament/Components/IPCNotFoundDialog.cs +++ b/osu.Game.Tournament/Components/IPCErrorDialog.cs @@ -6,14 +6,13 @@ using osu.Game.Overlays.Dialog; namespace osu.Game.Tournament.Components { - public class IPCNotFoundDialog : PopupDialog + public class IPCErrorDialog : PopupDialog { - public IPCNotFoundDialog() + public IPCErrorDialog(string headerText, string bodyText) { - BodyText = "Select a directory that contains an osu! Cutting Edge installation"; - - Icon = FontAwesome.Regular.Angry; - HeaderText = @"This is an invalid IPC Directory!"; + Icon = FontAwesome.Regular.SadTear; + HeaderText = headerText; + BodyText = bodyText; Buttons = new PopupDialogButton[] { new PopupDialogOkButton diff --git a/osu.Game.Tournament/IPC/FileBasedIPC.cs b/osu.Game.Tournament/IPC/FileBasedIPC.cs index 0454ef4e41..730779a46b 100644 --- a/osu.Game.Tournament/IPC/FileBasedIPC.cs +++ b/osu.Game.Tournament/IPC/FileBasedIPC.cs @@ -233,6 +233,7 @@ namespace osu.Game.Tournament.IPC private string findFromJsonConfig() { Logger.Log("Trying to find stable through the json config"); + if (tournamentStorage.Exists(stable_config)) { using (Stream stream = tournamentStorage.GetStream(stable_config, FileAccess.Read, FileMode.Open)) @@ -242,7 +243,7 @@ namespace osu.Game.Tournament.IPC return stableInfo.StablePath.Value; } } - + return null; } diff --git a/osu.Game.Tournament/Screens/SetupScreen.cs b/osu.Game.Tournament/Screens/SetupScreen.cs index dcaadc8247..4f6d063b10 100644 --- a/osu.Game.Tournament/Screens/SetupScreen.cs +++ b/osu.Game.Tournament/Screens/SetupScreen.cs @@ -82,7 +82,7 @@ namespace osu.Game.Tournament.Screens ButtonText = "Refresh", Action = () => { - stableInfo.StablePath.BindValueChanged(_ => + stableInfo.StablePath.BindValueChanged(_ => { fileBasedIpc?.LocateStableStorage(); Schedule(reload); diff --git a/osu.Game.Tournament/Screens/StablePathSelectScreen.cs b/osu.Game.Tournament/Screens/StablePathSelectScreen.cs index 8b75bd9290..35c2272918 100644 --- a/osu.Game.Tournament/Screens/StablePathSelectScreen.cs +++ b/osu.Game.Tournament/Screens/StablePathSelectScreen.cs @@ -171,7 +171,7 @@ namespace osu.Game.Tournament.Screens else { overlay = new DialogOverlay(); - overlay.Push(new IPCNotFoundDialog()); + overlay.Push(new IPCErrorDialog("This is an invalid IPC Directory", "Select a directory that contains an osu! stable cutting edge installation and make sure it has an empty ipc.txt file in it.")); AddInternal(overlay); Logger.Log("Folder is not an osu! stable CE directory"); // Return an error in the picker that the directory does not contain ipc.txt @@ -182,11 +182,12 @@ namespace osu.Game.Tournament.Screens { var fileBasedIpc = ipc as FileBasedIPC; fileBasedIpc?.LocateStableStorage(); + if (fileBasedIpc?.IPCStorage == null) { // Could not auto detect overlay = new DialogOverlay(); - overlay.Push(new IPCNotFoundDialog()); + overlay.Push(new IPCErrorDialog("Failed to auto detect", "An osu! stable cutting-edge installation could not be auto detected.\nPlease try and manually point to the directory.")); AddInternal(overlay); } else From 9bfdfbea43e14bbad24554a2d8758327882561a7 Mon Sep 17 00:00:00 2001 From: Shivam Date: Mon, 18 May 2020 00:47:31 +0200 Subject: [PATCH 10/59] Move stablestorage check to path selection screen Also forced stablepath to be empty during auto detection so it checks other sources to load ipc from --- osu.Game.Tournament/IPC/FileBasedIPC.cs | 15 +++++++-------- osu.Game.Tournament/Screens/SetupScreen.cs | 1 - .../Screens/StablePathSelectScreen.cs | 4 ++++ 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/osu.Game.Tournament/IPC/FileBasedIPC.cs b/osu.Game.Tournament/IPC/FileBasedIPC.cs index 730779a46b..6d1cd7cc3c 100644 --- a/osu.Game.Tournament/IPC/FileBasedIPC.cs +++ b/osu.Game.Tournament/IPC/FileBasedIPC.cs @@ -232,16 +232,15 @@ namespace osu.Game.Tournament.IPC private string findFromJsonConfig() { - Logger.Log("Trying to find stable through the json config"); - - if (tournamentStorage.Exists(stable_config)) + try { - using (Stream stream = tournamentStorage.GetStream(stable_config, FileAccess.Read, FileMode.Open)) - using (var sr = new StreamReader(stream)) - { - stableInfo = JsonConvert.DeserializeObject(sr.ReadToEnd()); + Logger.Log("Trying to find stable through the json config"); + + if (!string.IsNullOrEmpty(stableInfo.StablePath.Value)) return stableInfo.StablePath.Value; - } + } + catch + { } return null; diff --git a/osu.Game.Tournament/Screens/SetupScreen.cs b/osu.Game.Tournament/Screens/SetupScreen.cs index 4f6d063b10..e0fc98e031 100644 --- a/osu.Game.Tournament/Screens/SetupScreen.cs +++ b/osu.Game.Tournament/Screens/SetupScreen.cs @@ -84,7 +84,6 @@ namespace osu.Game.Tournament.Screens { stableInfo.StablePath.BindValueChanged(_ => { - fileBasedIpc?.LocateStableStorage(); Schedule(reload); }); sceneManager.SetScreen(new StablePathSelectScreen()); diff --git a/osu.Game.Tournament/Screens/StablePathSelectScreen.cs b/osu.Game.Tournament/Screens/StablePathSelectScreen.cs index 35c2272918..5c488ae352 100644 --- a/osu.Game.Tournament/Screens/StablePathSelectScreen.cs +++ b/osu.Game.Tournament/Screens/StablePathSelectScreen.cs @@ -142,6 +142,7 @@ namespace osu.Game.Tournament.Screens private void changePath(Storage storage) { var target = directorySelector.CurrentDirectory.Value.FullName; + Logger.Log($"Changing Stable CE location to {target}"); if (File.Exists(Path.Combine(target, "ipc.txt"))) { @@ -161,6 +162,8 @@ namespace osu.Game.Tournament.Screens })); } + var fileBasedIpc = ipc as FileBasedIPC; + fileBasedIpc?.LocateStableStorage(); sceneManager?.SetScreen(typeof(SetupScreen)); } catch (Exception e) @@ -180,6 +183,7 @@ namespace osu.Game.Tournament.Screens private void autoDetect() { + stableInfo.StablePath.Value = string.Empty; // This forces findStablePath() to look elsewhere. var fileBasedIpc = ipc as FileBasedIPC; fileBasedIpc?.LocateStableStorage(); From 7a839c1486cf96d322187474f34d3fd4f63c4b81 Mon Sep 17 00:00:00 2001 From: Shivam Date: Mon, 18 May 2020 00:50:08 +0200 Subject: [PATCH 11/59] Renamed Refresh button to Change source --- osu.Game.Tournament/Screens/SetupScreen.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tournament/Screens/SetupScreen.cs b/osu.Game.Tournament/Screens/SetupScreen.cs index e0fc98e031..478240f8b4 100644 --- a/osu.Game.Tournament/Screens/SetupScreen.cs +++ b/osu.Game.Tournament/Screens/SetupScreen.cs @@ -79,7 +79,7 @@ namespace osu.Game.Tournament.Screens new ActionableInfo { Label = "Current IPC source", - ButtonText = "Refresh", + ButtonText = "Change source", Action = () => { stableInfo.StablePath.BindValueChanged(_ => From a0a54efd4ec7f8ab4b1aaebf965cdd2e693fee4e Mon Sep 17 00:00:00 2001 From: Shivam Date: Mon, 18 May 2020 01:05:34 +0200 Subject: [PATCH 12/59] Fix test crashing because of sceneManager not being nullable --- osu.Game.Tournament/Screens/SetupScreen.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tournament/Screens/SetupScreen.cs b/osu.Game.Tournament/Screens/SetupScreen.cs index 478240f8b4..1c479bdec4 100644 --- a/osu.Game.Tournament/Screens/SetupScreen.cs +++ b/osu.Game.Tournament/Screens/SetupScreen.cs @@ -86,7 +86,7 @@ namespace osu.Game.Tournament.Screens { Schedule(reload); }); - sceneManager.SetScreen(new StablePathSelectScreen()); + sceneManager?.SetScreen(new StablePathSelectScreen()); }, Value = fileBasedIpc?.IPCStorage?.GetFullPath(string.Empty) ?? "Not found", Failing = fileBasedIpc?.IPCStorage == null, From e018d0744152e92df3e4559b7ce98551c30a57f2 Mon Sep 17 00:00:00 2001 From: Shivam Date: Wed, 20 May 2020 16:30:38 +0200 Subject: [PATCH 13/59] Use one constant for STABLE_CONFIG location string --- osu.Game.Tournament/IPC/FileBasedIPC.cs | 4 +--- osu.Game.Tournament/Models/StableInfo.cs | 4 ++++ osu.Game.Tournament/Screens/SetupScreen.cs | 1 - osu.Game.Tournament/Screens/StablePathSelectScreen.cs | 4 +--- osu.Game.Tournament/TournamentGameBase.cs | 8 ++++---- 5 files changed, 10 insertions(+), 11 deletions(-) diff --git a/osu.Game.Tournament/IPC/FileBasedIPC.cs b/osu.Game.Tournament/IPC/FileBasedIPC.cs index 6d1cd7cc3c..d2d74e94b2 100644 --- a/osu.Game.Tournament/IPC/FileBasedIPC.cs +++ b/osu.Game.Tournament/IPC/FileBasedIPC.cs @@ -40,8 +40,6 @@ namespace osu.Game.Tournament.IPC [Resolved] private StableInfo stableInfo { get; set; } - private const string stable_config = "tournament/stable.json"; - public Storage IPCStorage { get; private set; } [Resolved] @@ -196,7 +194,7 @@ namespace osu.Game.Tournament.IPC private void saveStablePath() { - using (var stream = tournamentStorage.GetStream(stable_config, FileAccess.Write, FileMode.Create)) + using (var stream = tournamentStorage.GetStream(StableInfo.STABLE_CONFIG, FileAccess.Write, FileMode.Create)) using (var sw = new StreamWriter(stream)) { sw.Write(JsonConvert.SerializeObject(stableInfo, diff --git a/osu.Game.Tournament/Models/StableInfo.cs b/osu.Game.Tournament/Models/StableInfo.cs index 4818842151..63423ca6fa 100644 --- a/osu.Game.Tournament/Models/StableInfo.cs +++ b/osu.Game.Tournament/Models/StableInfo.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using Newtonsoft.Json; using osu.Framework.Bindables; namespace osu.Game.Tournament.Models @@ -13,5 +14,8 @@ namespace osu.Game.Tournament.Models public class StableInfo { public Bindable StablePath = new Bindable(string.Empty); + + [JsonIgnore] + public const string STABLE_CONFIG = "tournament/stable.json"; } } diff --git a/osu.Game.Tournament/Screens/SetupScreen.cs b/osu.Game.Tournament/Screens/SetupScreen.cs index 1c479bdec4..9f8f81aa80 100644 --- a/osu.Game.Tournament/Screens/SetupScreen.cs +++ b/osu.Game.Tournament/Screens/SetupScreen.cs @@ -28,7 +28,6 @@ namespace osu.Game.Tournament.Screens private LoginOverlay loginOverlay; private ActionableInfo resolution; - private const string stable_config = "tournament/stable.json"; [Resolved] private MatchIPCInfo ipc { get; set; } diff --git a/osu.Game.Tournament/Screens/StablePathSelectScreen.cs b/osu.Game.Tournament/Screens/StablePathSelectScreen.cs index 5c488ae352..a42a5dc0fc 100644 --- a/osu.Game.Tournament/Screens/StablePathSelectScreen.cs +++ b/osu.Game.Tournament/Screens/StablePathSelectScreen.cs @@ -26,8 +26,6 @@ namespace osu.Game.Tournament.Screens { private DirectorySelector directorySelector; - private const string stable_config = "tournament/stable.json"; - [Resolved] private StableInfo stableInfo { get; set; } @@ -150,7 +148,7 @@ namespace osu.Game.Tournament.Screens try { - using (var stream = storage.GetStream(stable_config, FileAccess.Write, FileMode.Create)) + using (var stream = storage.GetStream(StableInfo.STABLE_CONFIG, FileAccess.Write, FileMode.Create)) using (var sw = new StreamWriter(stream)) { sw.Write(JsonConvert.SerializeObject(stableInfo, diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index 31c56c7fc4..00946399fb 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -147,7 +147,10 @@ namespace osu.Game.Tournament private void readStableConfig() { - if (storage.Exists(stable_config)) + if (stableInfo == null) + stableInfo = new StableInfo(); + + if (storage.Exists(StableInfo.STABLE_CONFIG)) { using (Stream stream = storage.GetStream(stable_config, FileAccess.Read, FileMode.Open)) using (var sr = new StreamReader(stream)) @@ -156,9 +159,6 @@ namespace osu.Game.Tournament } } - if (stableInfo == null) - stableInfo = new StableInfo(); - dependencies.Cache(stableInfo); } From 15ebe38303307f7bd5b6a24bc10bf72c3b926690 Mon Sep 17 00:00:00 2001 From: Shivam Date: Wed, 20 May 2020 17:13:35 +0200 Subject: [PATCH 14/59] Return null if path is not found, for clarity --- osu.Game.Tournament/IPC/FileBasedIPC.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tournament/IPC/FileBasedIPC.cs b/osu.Game.Tournament/IPC/FileBasedIPC.cs index d2d74e94b2..875bc4b4cd 100644 --- a/osu.Game.Tournament/IPC/FileBasedIPC.cs +++ b/osu.Game.Tournament/IPC/FileBasedIPC.cs @@ -184,7 +184,7 @@ namespace osu.Game.Tournament.IPC } } - return stableInstallPath; + return null; } finally { From b1c957c5e1aec15b346cbbd61db973bdce1a1f76 Mon Sep 17 00:00:00 2001 From: Shivam Date: Wed, 20 May 2020 17:25:53 +0200 Subject: [PATCH 15/59] invert if-statement and early return + reuse of checkExists --- osu.Game.Tournament/IPC/FileBasedIPC.cs | 2 +- .../Screens/StablePathSelectScreen.cs | 56 +++++++++---------- 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/osu.Game.Tournament/IPC/FileBasedIPC.cs b/osu.Game.Tournament/IPC/FileBasedIPC.cs index 875bc4b4cd..cc19c9eaba 100644 --- a/osu.Game.Tournament/IPC/FileBasedIPC.cs +++ b/osu.Game.Tournament/IPC/FileBasedIPC.cs @@ -157,7 +157,7 @@ namespace osu.Game.Tournament.IPC return IPCStorage; } - private static bool checkExists(string p) => File.Exists(Path.Combine(p, "ipc.txt")); + public bool checkExists(string p) => File.Exists(Path.Combine(p, "ipc.txt")); private string findStablePath() { diff --git a/osu.Game.Tournament/Screens/StablePathSelectScreen.cs b/osu.Game.Tournament/Screens/StablePathSelectScreen.cs index a42a5dc0fc..dbb7a3b900 100644 --- a/osu.Game.Tournament/Screens/StablePathSelectScreen.cs +++ b/osu.Game.Tournament/Screens/StablePathSelectScreen.cs @@ -140,43 +140,43 @@ namespace osu.Game.Tournament.Screens private void changePath(Storage storage) { var target = directorySelector.CurrentDirectory.Value.FullName; + var fileBasedIpc = ipc as FileBasedIPC; Logger.Log($"Changing Stable CE location to {target}"); - if (File.Exists(Path.Combine(target, "ipc.txt"))) - { - stableInfo.StablePath.Value = target; - - try - { - using (var stream = storage.GetStream(StableInfo.STABLE_CONFIG, FileAccess.Write, FileMode.Create)) - using (var sw = new StreamWriter(stream)) - { - sw.Write(JsonConvert.SerializeObject(stableInfo, - new JsonSerializerSettings - { - Formatting = Formatting.Indented, - NullValueHandling = NullValueHandling.Ignore, - DefaultValueHandling = DefaultValueHandling.Ignore, - })); - } - - var fileBasedIpc = ipc as FileBasedIPC; - fileBasedIpc?.LocateStableStorage(); - sceneManager?.SetScreen(typeof(SetupScreen)); - } - catch (Exception e) - { - Logger.Log($"Error during migration: {e.Message}", level: LogLevel.Error); - } - } - else + if (!fileBasedIpc.checkExists(target)) { overlay = new DialogOverlay(); overlay.Push(new IPCErrorDialog("This is an invalid IPC Directory", "Select a directory that contains an osu! stable cutting edge installation and make sure it has an empty ipc.txt file in it.")); AddInternal(overlay); Logger.Log("Folder is not an osu! stable CE directory"); + return; // Return an error in the picker that the directory does not contain ipc.txt } + + stableInfo.StablePath.Value = target; + + try + { + using (var stream = storage.GetStream(StableInfo.STABLE_CONFIG, FileAccess.Write, FileMode.Create)) + using (var sw = new StreamWriter(stream)) + { + sw.Write(JsonConvert.SerializeObject(stableInfo, + new JsonSerializerSettings + { + Formatting = Formatting.Indented, + NullValueHandling = NullValueHandling.Ignore, + DefaultValueHandling = DefaultValueHandling.Ignore, + })); + } + + + fileBasedIpc?.LocateStableStorage(); + sceneManager?.SetScreen(typeof(SetupScreen)); + } + catch (Exception e) + { + Logger.Log($"Error during migration: {e.Message}", level: LogLevel.Error); + } } private void autoDetect() From a5c2f97a76d0700d3498a78041160354f7851da4 Mon Sep 17 00:00:00 2001 From: Shivam Date: Wed, 20 May 2020 22:15:51 +0200 Subject: [PATCH 16/59] use common const in TournamentGameBase --- osu.Game.Tournament/TournamentGameBase.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index 00946399fb..7d7d4f84aa 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -33,8 +33,6 @@ namespace osu.Game.Tournament { private const string bracket_filename = "bracket.json"; - private const string stable_config = "tournament/stable.json"; - private LadderInfo ladder; private Storage storage; @@ -152,7 +150,7 @@ namespace osu.Game.Tournament if (storage.Exists(StableInfo.STABLE_CONFIG)) { - using (Stream stream = storage.GetStream(stable_config, FileAccess.Read, FileMode.Open)) + using (Stream stream = storage.GetStream(StableInfo.STABLE_CONFIG, FileAccess.Read, FileMode.Open)) using (var sr = new StreamReader(stream)) { stableInfo = JsonConvert.DeserializeObject(sr.ReadToEnd()); From d2416ce30d6e5a8925310a1fae04fc97ceedf6d3 Mon Sep 17 00:00:00 2001 From: Shivam Date: Wed, 20 May 2020 22:16:37 +0200 Subject: [PATCH 17/59] removed redundant code and use existing checkExists --- osu.Game.Tournament/IPC/FileBasedIPC.cs | 25 +++-------- .../Screens/StablePathSelectScreen.cs | 44 +++++++------------ 2 files changed, 21 insertions(+), 48 deletions(-) diff --git a/osu.Game.Tournament/IPC/FileBasedIPC.cs b/osu.Game.Tournament/IPC/FileBasedIPC.cs index cc19c9eaba..74de5904e8 100644 --- a/osu.Game.Tournament/IPC/FileBasedIPC.cs +++ b/osu.Game.Tournament/IPC/FileBasedIPC.cs @@ -167,7 +167,7 @@ namespace osu.Game.Tournament.IPC { List> stableFindMethods = new List> { - findFromJsonConfig, + readFromStableInfo, findFromEnvVar, findFromRegistry, findFromLocalAppData, @@ -180,6 +180,7 @@ namespace osu.Game.Tournament.IPC if (stableInstallPath != null) { + saveStablePath(stableInstallPath); return stableInstallPath; } } @@ -192,8 +193,10 @@ namespace osu.Game.Tournament.IPC } } - private void saveStablePath() + private void saveStablePath(string path) { + stableInfo.StablePath.Value = path; + using (var stream = tournamentStorage.GetStream(StableInfo.STABLE_CONFIG, FileAccess.Write, FileMode.Create)) using (var sw = new StreamWriter(stream)) { @@ -215,11 +218,7 @@ namespace osu.Game.Tournament.IPC string stableInstallPath = Environment.GetEnvironmentVariable("OSU_STABLE_PATH"); if (checkExists(stableInstallPath)) - { - stableInfo.StablePath.Value = stableInstallPath; - saveStablePath(); return stableInstallPath; - } } catch { @@ -228,7 +227,7 @@ namespace osu.Game.Tournament.IPC return null; } - private string findFromJsonConfig() + private string readFromStableInfo() { try { @@ -250,11 +249,7 @@ namespace osu.Game.Tournament.IPC string stableInstallPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), @"osu!"); if (checkExists(stableInstallPath)) - { - stableInfo.StablePath.Value = stableInstallPath; - saveStablePath(); return stableInstallPath; - } return null; } @@ -265,11 +260,7 @@ namespace osu.Game.Tournament.IPC string stableInstallPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".osu"); if (checkExists(stableInstallPath)) - { - stableInfo.StablePath.Value = stableInstallPath; - saveStablePath(); return stableInstallPath; - } return null; } @@ -284,11 +275,7 @@ namespace osu.Game.Tournament.IPC stableInstallPath = key?.OpenSubKey(@"shell\open\command")?.GetValue(string.Empty).ToString().Split('"')[1].Replace("osu!.exe", ""); if (checkExists(stableInstallPath)) - { - stableInfo.StablePath.Value = stableInstallPath; - saveStablePath(); return stableInstallPath; - } return null; } diff --git a/osu.Game.Tournament/Screens/StablePathSelectScreen.cs b/osu.Game.Tournament/Screens/StablePathSelectScreen.cs index dbb7a3b900..68fdaa34f8 100644 --- a/osu.Game.Tournament/Screens/StablePathSelectScreen.cs +++ b/osu.Game.Tournament/Screens/StablePathSelectScreen.cs @@ -139,39 +139,26 @@ namespace osu.Game.Tournament.Screens private void changePath(Storage storage) { - var target = directorySelector.CurrentDirectory.Value.FullName; - var fileBasedIpc = ipc as FileBasedIPC; - Logger.Log($"Changing Stable CE location to {target}"); - - if (!fileBasedIpc.checkExists(target)) - { - overlay = new DialogOverlay(); - overlay.Push(new IPCErrorDialog("This is an invalid IPC Directory", "Select a directory that contains an osu! stable cutting edge installation and make sure it has an empty ipc.txt file in it.")); - AddInternal(overlay); - Logger.Log("Folder is not an osu! stable CE directory"); - return; - // Return an error in the picker that the directory does not contain ipc.txt - } - - stableInfo.StablePath.Value = target; - try { - using (var stream = storage.GetStream(StableInfo.STABLE_CONFIG, FileAccess.Write, FileMode.Create)) - using (var sw = new StreamWriter(stream)) + var target = directorySelector.CurrentDirectory.Value.FullName; + stableInfo.StablePath.Value = target; + var fileBasedIpc = ipc as FileBasedIPC; + Logger.Log($"Changing Stable CE location to {target}"); + + if (!fileBasedIpc.checkExists(target)) { - sw.Write(JsonConvert.SerializeObject(stableInfo, - new JsonSerializerSettings - { - Formatting = Formatting.Indented, - NullValueHandling = NullValueHandling.Ignore, - DefaultValueHandling = DefaultValueHandling.Ignore, - })); + overlay = new DialogOverlay(); + overlay.Push(new IPCErrorDialog("This is an invalid IPC Directory", "Select a directory that contains an osu! stable cutting edge installation and make sure it has an empty ipc.txt file in it.")); + AddInternal(overlay); + Logger.Log("Folder is not an osu! stable CE directory"); + return; + // Return an error in the picker that the directory does not contain ipc.txt } - - fileBasedIpc?.LocateStableStorage(); - sceneManager?.SetScreen(typeof(SetupScreen)); + + fileBasedIpc.LocateStableStorage(); + sceneManager.SetScreen(typeof(SetupScreen)); } catch (Exception e) { @@ -181,7 +168,6 @@ namespace osu.Game.Tournament.Screens private void autoDetect() { - stableInfo.StablePath.Value = string.Empty; // This forces findStablePath() to look elsewhere. var fileBasedIpc = ipc as FileBasedIPC; fileBasedIpc?.LocateStableStorage(); From 585100207c05cb0bd0ddd50db488bbba15b53c60 Mon Sep 17 00:00:00 2001 From: Shivam Date: Wed, 20 May 2020 22:30:31 +0200 Subject: [PATCH 18/59] make CheckExists static public and removed unnecessary code --- osu.Game.Tournament/IPC/FileBasedIPC.cs | 10 ++--- .../Screens/StablePathSelectScreen.cs | 40 +++++++------------ 2 files changed, 20 insertions(+), 30 deletions(-) diff --git a/osu.Game.Tournament/IPC/FileBasedIPC.cs b/osu.Game.Tournament/IPC/FileBasedIPC.cs index 74de5904e8..d93bce8dfa 100644 --- a/osu.Game.Tournament/IPC/FileBasedIPC.cs +++ b/osu.Game.Tournament/IPC/FileBasedIPC.cs @@ -157,7 +157,7 @@ namespace osu.Game.Tournament.IPC return IPCStorage; } - public bool checkExists(string p) => File.Exists(Path.Combine(p, "ipc.txt")); + public static bool CheckExists(string p) => File.Exists(Path.Combine(p, "ipc.txt")); private string findStablePath() { @@ -217,7 +217,7 @@ namespace osu.Game.Tournament.IPC Logger.Log("Trying to find stable with environment variables"); string stableInstallPath = Environment.GetEnvironmentVariable("OSU_STABLE_PATH"); - if (checkExists(stableInstallPath)) + if (CheckExists(stableInstallPath)) return stableInstallPath; } catch @@ -248,7 +248,7 @@ namespace osu.Game.Tournament.IPC Logger.Log("Trying to find stable in %LOCALAPPDATA%"); string stableInstallPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), @"osu!"); - if (checkExists(stableInstallPath)) + if (CheckExists(stableInstallPath)) return stableInstallPath; return null; @@ -259,7 +259,7 @@ namespace osu.Game.Tournament.IPC Logger.Log("Trying to find stable in dotfolders"); string stableInstallPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".osu"); - if (checkExists(stableInstallPath)) + if (CheckExists(stableInstallPath)) return stableInstallPath; return null; @@ -274,7 +274,7 @@ namespace osu.Game.Tournament.IPC using (RegistryKey key = Registry.ClassesRoot.OpenSubKey("osu")) stableInstallPath = key?.OpenSubKey(@"shell\open\command")?.GetValue(string.Empty).ToString().Split('"')[1].Replace("osu!.exe", ""); - if (checkExists(stableInstallPath)) + if (CheckExists(stableInstallPath)) return stableInstallPath; return null; diff --git a/osu.Game.Tournament/Screens/StablePathSelectScreen.cs b/osu.Game.Tournament/Screens/StablePathSelectScreen.cs index 68fdaa34f8..dcc26b8b1e 100644 --- a/osu.Game.Tournament/Screens/StablePathSelectScreen.cs +++ b/osu.Game.Tournament/Screens/StablePathSelectScreen.cs @@ -1,9 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; using System.IO; -using Newtonsoft.Json; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -139,31 +137,23 @@ namespace osu.Game.Tournament.Screens private void changePath(Storage storage) { - try + var target = directorySelector.CurrentDirectory.Value.FullName; + stableInfo.StablePath.Value = target; + Logger.Log($"Changing Stable CE location to {target}"); + + if (!FileBasedIPC.CheckExists(target)) { - var target = directorySelector.CurrentDirectory.Value.FullName; - stableInfo.StablePath.Value = target; - var fileBasedIpc = ipc as FileBasedIPC; - Logger.Log($"Changing Stable CE location to {target}"); - - if (!fileBasedIpc.checkExists(target)) - { - overlay = new DialogOverlay(); - overlay.Push(new IPCErrorDialog("This is an invalid IPC Directory", "Select a directory that contains an osu! stable cutting edge installation and make sure it has an empty ipc.txt file in it.")); - AddInternal(overlay); - Logger.Log("Folder is not an osu! stable CE directory"); - return; - // Return an error in the picker that the directory does not contain ipc.txt - } - - - fileBasedIpc.LocateStableStorage(); - sceneManager.SetScreen(typeof(SetupScreen)); - } - catch (Exception e) - { - Logger.Log($"Error during migration: {e.Message}", level: LogLevel.Error); + overlay = new DialogOverlay(); + overlay.Push(new IPCErrorDialog("This is an invalid IPC Directory", "Select a directory that contains an osu! stable cutting edge installation and make sure it has an empty ipc.txt file in it.")); + AddInternal(overlay); + Logger.Log("Folder is not an osu! stable CE directory"); + return; + // Return an error in the picker that the directory does not contain ipc.txt } + + var fileBasedIpc = ipc as FileBasedIPC; + fileBasedIpc?.LocateStableStorage(); + sceneManager?.SetScreen(typeof(SetupScreen)); } private void autoDetect() From 0717dab8e4b730fcb11ff5d422ddf2f418aad01d Mon Sep 17 00:00:00 2001 From: Shivam Date: Fri, 22 May 2020 19:51:08 +0200 Subject: [PATCH 19/59] Add StablePathSelectScreen visual test --- .../TestSceneStablePathSelectScreens.cs | 30 +++++++++++++++++++ .../Screens/StablePathSelectScreen.cs | 5 ++-- 2 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 osu.Game.Tournament.Tests/Screens/TestSceneStablePathSelectScreens.cs diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneStablePathSelectScreens.cs b/osu.Game.Tournament.Tests/Screens/TestSceneStablePathSelectScreens.cs new file mode 100644 index 0000000000..f0c89ba4ca --- /dev/null +++ b/osu.Game.Tournament.Tests/Screens/TestSceneStablePathSelectScreens.cs @@ -0,0 +1,30 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Tournament.Screens; +using osu.Framework.Platform; + +namespace osu.Game.Tournament.Tests.Screens +{ + public class TestSceneStablePathSelectScreens : TournamentTestScene + { + + public TestSceneStablePathSelectScreens() + { + AddStep("Add screen", () => Add(new TestSceneStablePathSelectScreen())); + } + + private class TestSceneStablePathSelectScreen : StablePathSelectScreen + { + protected override void changePath(Storage storage) + { + Expire(); + } + + protected override void autoDetect() + { + Expire(); + } + } + } +} diff --git a/osu.Game.Tournament/Screens/StablePathSelectScreen.cs b/osu.Game.Tournament/Screens/StablePathSelectScreen.cs index dcc26b8b1e..f706c42e1d 100644 --- a/osu.Game.Tournament/Screens/StablePathSelectScreen.cs +++ b/osu.Game.Tournament/Screens/StablePathSelectScreen.cs @@ -14,6 +14,7 @@ using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Overlays; +using osu.Game.Overlays.Dialog; using osu.Game.Tournament.IPC; using osu.Game.Tournament.Components; using osuTK; @@ -135,7 +136,7 @@ namespace osu.Game.Tournament.Screens }); } - private void changePath(Storage storage) + protected virtual void changePath(Storage storage) { var target = directorySelector.CurrentDirectory.Value.FullName; stableInfo.StablePath.Value = target; @@ -156,7 +157,7 @@ namespace osu.Game.Tournament.Screens sceneManager?.SetScreen(typeof(SetupScreen)); } - private void autoDetect() + protected virtual void autoDetect() { var fileBasedIpc = ipc as FileBasedIPC; fileBasedIpc?.LocateStableStorage(); From c6345ba6c94c41e53108b317c3199a3c98ed2cc1 Mon Sep 17 00:00:00 2001 From: Shivam Date: Fri, 22 May 2020 20:01:26 +0200 Subject: [PATCH 20/59] corrected styling issues --- .../Screens/TestSceneStablePathSelectScreens.cs | 5 ++--- osu.Game.Tournament/Screens/StablePathSelectScreen.cs | 9 ++++----- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneStablePathSelectScreens.cs b/osu.Game.Tournament.Tests/Screens/TestSceneStablePathSelectScreens.cs index f0c89ba4ca..4dfd4d35c8 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneStablePathSelectScreens.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneStablePathSelectScreens.cs @@ -8,7 +8,6 @@ namespace osu.Game.Tournament.Tests.Screens { public class TestSceneStablePathSelectScreens : TournamentTestScene { - public TestSceneStablePathSelectScreens() { AddStep("Add screen", () => Add(new TestSceneStablePathSelectScreen())); @@ -16,12 +15,12 @@ namespace osu.Game.Tournament.Tests.Screens private class TestSceneStablePathSelectScreen : StablePathSelectScreen { - protected override void changePath(Storage storage) + protected override void ChangePath(Storage storage) { Expire(); } - protected override void autoDetect() + protected override void AutoDetect() { Expire(); } diff --git a/osu.Game.Tournament/Screens/StablePathSelectScreen.cs b/osu.Game.Tournament/Screens/StablePathSelectScreen.cs index f706c42e1d..609c601106 100644 --- a/osu.Game.Tournament/Screens/StablePathSelectScreen.cs +++ b/osu.Game.Tournament/Screens/StablePathSelectScreen.cs @@ -14,7 +14,6 @@ using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Overlays; -using osu.Game.Overlays.Dialog; using osu.Game.Tournament.IPC; using osu.Game.Tournament.Components; using osuTK; @@ -109,7 +108,7 @@ namespace osu.Game.Tournament.Screens Origin = Anchor.Centre, Width = 300, Text = "Select stable path", - Action = () => changePath(storage) + Action = () => ChangePath(storage) }, new TriangleButton { @@ -117,7 +116,7 @@ namespace osu.Game.Tournament.Screens Origin = Anchor.Centre, Width = 300, Text = "Auto detect", - Action = autoDetect + Action = AutoDetect }, } } @@ -136,7 +135,7 @@ namespace osu.Game.Tournament.Screens }); } - protected virtual void changePath(Storage storage) + protected virtual void ChangePath(Storage storage) { var target = directorySelector.CurrentDirectory.Value.FullName; stableInfo.StablePath.Value = target; @@ -157,7 +156,7 @@ namespace osu.Game.Tournament.Screens sceneManager?.SetScreen(typeof(SetupScreen)); } - protected virtual void autoDetect() + protected virtual void AutoDetect() { var fileBasedIpc = ipc as FileBasedIPC; fileBasedIpc?.LocateStableStorage(); From 4c3900cfc8a390f61b0252abec07cb61f6309c87 Mon Sep 17 00:00:00 2001 From: Shivam Date: Mon, 25 May 2020 17:16:40 +0200 Subject: [PATCH 21/59] Remove unnecessary comments, simplify initialPath and clarified TestScene name --- .../Screens/TestSceneStablePathSelectScreens.cs | 8 ++++---- osu.Game.Tournament/Screens/StablePathSelectScreen.cs | 11 +---------- 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneStablePathSelectScreens.cs b/osu.Game.Tournament.Tests/Screens/TestSceneStablePathSelectScreens.cs index 4dfd4d35c8..ce0626dd0f 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneStablePathSelectScreens.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneStablePathSelectScreens.cs @@ -6,14 +6,14 @@ using osu.Framework.Platform; namespace osu.Game.Tournament.Tests.Screens { - public class TestSceneStablePathSelectScreens : TournamentTestScene + public class TestSceneStablePathSelectScreen : TournamentTestScene { - public TestSceneStablePathSelectScreens() + public TestSceneStablePathSelectScreen() { - AddStep("Add screen", () => Add(new TestSceneStablePathSelectScreen())); + AddStep("Add screen", () => Add(new StablePathSelectTestScreen())); } - private class TestSceneStablePathSelectScreen : StablePathSelectScreen + private class StablePathSelectTestScreen : StablePathSelectScreen { protected override void ChangePath(Storage storage) { diff --git a/osu.Game.Tournament/Screens/StablePathSelectScreen.cs b/osu.Game.Tournament/Screens/StablePathSelectScreen.cs index 609c601106..d2c7225909 100644 --- a/osu.Game.Tournament/Screens/StablePathSelectScreen.cs +++ b/osu.Game.Tournament/Screens/StablePathSelectScreen.cs @@ -38,14 +38,7 @@ namespace osu.Game.Tournament.Screens [BackgroundDependencyLoader(true)] private void load(Storage storage, OsuColour colours) { - // begin selection in the parent directory of the current storage location - var initialPath = new DirectoryInfo(storage.GetFullPath(string.Empty)).Parent?.FullName; - - if (!string.IsNullOrEmpty(stableInfo.StablePath.Value)) - { - // If the original path info for osu! stable is not empty, set it to the parent directory of that location - initialPath = new DirectoryInfo(stableInfo.StablePath.Value).Parent?.FullName; - } + var initialPath = new DirectoryInfo(storage.GetFullPath(stableInfo.StablePath.Value ?? string.Empty)).Parent?.FullName; AddRangeInternal(new Drawable[] { @@ -148,7 +141,6 @@ namespace osu.Game.Tournament.Screens AddInternal(overlay); Logger.Log("Folder is not an osu! stable CE directory"); return; - // Return an error in the picker that the directory does not contain ipc.txt } var fileBasedIpc = ipc as FileBasedIPC; @@ -163,7 +155,6 @@ namespace osu.Game.Tournament.Screens if (fileBasedIpc?.IPCStorage == null) { - // Could not auto detect overlay = new DialogOverlay(); overlay.Push(new IPCErrorDialog("Failed to auto detect", "An osu! stable cutting-edge installation could not be auto detected.\nPlease try and manually point to the directory.")); AddInternal(overlay); From 7ae2383288109693324d02cb6c39805a4df0a3f4 Mon Sep 17 00:00:00 2001 From: Shivam Date: Thu, 28 May 2020 15:03:49 +0200 Subject: [PATCH 22/59] move stable config declaration and initial reading --- osu.Game.Tournament/IPC/FileBasedIPC.cs | 29 +++++++----------------- osu.Game.Tournament/Models/StableInfo.cs | 2 -- 2 files changed, 8 insertions(+), 23 deletions(-) diff --git a/osu.Game.Tournament/IPC/FileBasedIPC.cs b/osu.Game.Tournament/IPC/FileBasedIPC.cs index d93bce8dfa..6a403c5a6a 100644 --- a/osu.Game.Tournament/IPC/FileBasedIPC.cs +++ b/osu.Game.Tournament/IPC/FileBasedIPC.cs @@ -39,6 +39,7 @@ namespace osu.Game.Tournament.IPC [Resolved] private StableInfo stableInfo { get; set; } + private const string STABLE_CONFIG = "tournament/stable.json"; public Storage IPCStorage { get; private set; } @@ -161,13 +162,14 @@ namespace osu.Game.Tournament.IPC private string findStablePath() { - string stableInstallPath = string.Empty; + if (!string.IsNullOrEmpty(stableInfo.StablePath.Value)) + return stableInfo.StablePath.Value; + string stableInstallPath = string.Empty; try { List> stableFindMethods = new List> { - readFromStableInfo, findFromEnvVar, findFromRegistry, findFromLocalAppData, @@ -180,7 +182,7 @@ namespace osu.Game.Tournament.IPC if (stableInstallPath != null) { - saveStablePath(stableInstallPath); + saveStableConfig(stableInstallPath); return stableInstallPath; } } @@ -193,11 +195,12 @@ namespace osu.Game.Tournament.IPC } } - private void saveStablePath(string path) + + private void saveStableConfig(string path) { stableInfo.StablePath.Value = path; - using (var stream = tournamentStorage.GetStream(StableInfo.STABLE_CONFIG, FileAccess.Write, FileMode.Create)) + using (var stream = tournamentStorage.GetStream(STABLE_CONFIG, FileAccess.Write, FileMode.Create)) using (var sw = new StreamWriter(stream)) { sw.Write(JsonConvert.SerializeObject(stableInfo, @@ -227,22 +230,6 @@ namespace osu.Game.Tournament.IPC return null; } - private string readFromStableInfo() - { - try - { - Logger.Log("Trying to find stable through the json config"); - - if (!string.IsNullOrEmpty(stableInfo.StablePath.Value)) - return stableInfo.StablePath.Value; - } - catch - { - } - - return null; - } - private string findFromLocalAppData() { Logger.Log("Trying to find stable in %LOCALAPPDATA%"); diff --git a/osu.Game.Tournament/Models/StableInfo.cs b/osu.Game.Tournament/Models/StableInfo.cs index 63423ca6fa..873e1c5e25 100644 --- a/osu.Game.Tournament/Models/StableInfo.cs +++ b/osu.Game.Tournament/Models/StableInfo.cs @@ -15,7 +15,5 @@ namespace osu.Game.Tournament.Models { public Bindable StablePath = new Bindable(string.Empty); - [JsonIgnore] - public const string STABLE_CONFIG = "tournament/stable.json"; } } From 3731e76b10b99a1307e222355efe95df3a5efb2d Mon Sep 17 00:00:00 2001 From: Shivam Date: Thu, 28 May 2020 15:28:27 +0200 Subject: [PATCH 23/59] Move stable_config declaration, rename testscene --- ...thSelectScreens.cs => TestSceneStablePathSelectScreen.cs} | 0 osu.Game.Tournament/IPC/FileBasedIPC.cs | 5 +++-- osu.Game.Tournament/Models/StableInfo.cs | 2 -- osu.Game.Tournament/Screens/StablePathSelectScreen.cs | 2 +- osu.Game.Tournament/TournamentGameBase.cs | 4 ++-- 5 files changed, 6 insertions(+), 7 deletions(-) rename osu.Game.Tournament.Tests/Screens/{TestSceneStablePathSelectScreens.cs => TestSceneStablePathSelectScreen.cs} (100%) diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneStablePathSelectScreens.cs b/osu.Game.Tournament.Tests/Screens/TestSceneStablePathSelectScreen.cs similarity index 100% rename from osu.Game.Tournament.Tests/Screens/TestSceneStablePathSelectScreens.cs rename to osu.Game.Tournament.Tests/Screens/TestSceneStablePathSelectScreen.cs diff --git a/osu.Game.Tournament/IPC/FileBasedIPC.cs b/osu.Game.Tournament/IPC/FileBasedIPC.cs index 6a403c5a6a..8518b7f8da 100644 --- a/osu.Game.Tournament/IPC/FileBasedIPC.cs +++ b/osu.Game.Tournament/IPC/FileBasedIPC.cs @@ -39,7 +39,8 @@ namespace osu.Game.Tournament.IPC [Resolved] private StableInfo stableInfo { get; set; } - private const string STABLE_CONFIG = "tournament/stable.json"; + + public const string STABLE_CONFIG = "tournament/stable.json"; public Storage IPCStorage { get; private set; } @@ -166,6 +167,7 @@ namespace osu.Game.Tournament.IPC return stableInfo.StablePath.Value; string stableInstallPath = string.Empty; + try { List> stableFindMethods = new List> @@ -195,7 +197,6 @@ namespace osu.Game.Tournament.IPC } } - private void saveStableConfig(string path) { stableInfo.StablePath.Value = path; diff --git a/osu.Game.Tournament/Models/StableInfo.cs b/osu.Game.Tournament/Models/StableInfo.cs index 873e1c5e25..4818842151 100644 --- a/osu.Game.Tournament/Models/StableInfo.cs +++ b/osu.Game.Tournament/Models/StableInfo.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System; -using Newtonsoft.Json; using osu.Framework.Bindables; namespace osu.Game.Tournament.Models @@ -14,6 +13,5 @@ namespace osu.Game.Tournament.Models public class StableInfo { public Bindable StablePath = new Bindable(string.Empty); - } } diff --git a/osu.Game.Tournament/Screens/StablePathSelectScreen.cs b/osu.Game.Tournament/Screens/StablePathSelectScreen.cs index d2c7225909..eace3c78d5 100644 --- a/osu.Game.Tournament/Screens/StablePathSelectScreen.cs +++ b/osu.Game.Tournament/Screens/StablePathSelectScreen.cs @@ -38,7 +38,7 @@ namespace osu.Game.Tournament.Screens [BackgroundDependencyLoader(true)] private void load(Storage storage, OsuColour colours) { - var initialPath = new DirectoryInfo(storage.GetFullPath(stableInfo.StablePath.Value ?? string.Empty)).Parent?.FullName; + var initialPath = new DirectoryInfo(storage.GetFullPath(stableInfo.StablePath.Value ?? string.Empty)).Parent?.FullName; AddRangeInternal(new Drawable[] { diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index 7d7d4f84aa..dcfe646390 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -148,9 +148,9 @@ namespace osu.Game.Tournament if (stableInfo == null) stableInfo = new StableInfo(); - if (storage.Exists(StableInfo.STABLE_CONFIG)) + if (storage.Exists(FileBasedIPC.STABLE_CONFIG)) { - using (Stream stream = storage.GetStream(StableInfo.STABLE_CONFIG, FileAccess.Read, FileMode.Open)) + using (Stream stream = storage.GetStream(FileBasedIPC.STABLE_CONFIG, FileAccess.Read, FileMode.Open)) using (var sr = new StreamReader(stream)) { stableInfo = JsonConvert.DeserializeObject(sr.ReadToEnd()); From 0027f44bd0d0a099a4bd1ce1b5a053b3c771d1b3 Mon Sep 17 00:00:00 2001 From: Shivam Date: Sun, 31 May 2020 16:27:05 +0200 Subject: [PATCH 24/59] Moved stableInfo read to FileBasedIPC DI is also not needed anymore to access StableInfo, this goes through FileBasedIPC. Note: directory selector now always navigates to the osu! lazer base path. --- osu.Game.Tournament/IPC/FileBasedIPC.cs | 30 +++++++++++++++---- osu.Game.Tournament/Screens/SetupScreen.cs | 12 ++------ .../Screens/StablePathSelectScreen.cs | 10 ++----- osu.Game.Tournament/TournamentGameBase.cs | 19 ------------ 4 files changed, 31 insertions(+), 40 deletions(-) diff --git a/osu.Game.Tournament/IPC/FileBasedIPC.cs b/osu.Game.Tournament/IPC/FileBasedIPC.cs index 8518b7f8da..4ec9d2012a 100644 --- a/osu.Game.Tournament/IPC/FileBasedIPC.cs +++ b/osu.Game.Tournament/IPC/FileBasedIPC.cs @@ -37,8 +37,7 @@ namespace osu.Game.Tournament.IPC private int lastBeatmapId; private ScheduledDelegate scheduled; - [Resolved] - private StableInfo stableInfo { get; set; } + private StableInfo stableInfo; public const string STABLE_CONFIG = "tournament/stable.json"; @@ -161,9 +160,11 @@ namespace osu.Game.Tournament.IPC public static bool CheckExists(string p) => File.Exists(Path.Combine(p, "ipc.txt")); + public StableInfo GetStableInfo() => stableInfo; + private string findStablePath() { - if (!string.IsNullOrEmpty(stableInfo.StablePath.Value)) + if (!string.IsNullOrEmpty(readStableConfig())) return stableInfo.StablePath.Value; string stableInstallPath = string.Empty; @@ -184,7 +185,7 @@ namespace osu.Game.Tournament.IPC if (stableInstallPath != null) { - saveStableConfig(stableInstallPath); + SaveStableConfig(stableInstallPath); return stableInstallPath; } } @@ -197,7 +198,7 @@ namespace osu.Game.Tournament.IPC } } - private void saveStableConfig(string path) + public void SaveStableConfig(string path) { stableInfo.StablePath.Value = path; @@ -214,6 +215,25 @@ namespace osu.Game.Tournament.IPC } } + private string readStableConfig() + { + if (stableInfo == null) + stableInfo = new StableInfo(); + + if (tournamentStorage.Exists(FileBasedIPC.STABLE_CONFIG)) + { + using (Stream stream = tournamentStorage.GetStream(FileBasedIPC.STABLE_CONFIG, FileAccess.Read, FileMode.Open)) + using (var sr = new StreamReader(stream)) + { + stableInfo = JsonConvert.DeserializeObject(sr.ReadToEnd()); + } + + return stableInfo.StablePath.Value; + } + + return null; + } + private string findFromEnvVar() { try diff --git a/osu.Game.Tournament/Screens/SetupScreen.cs b/osu.Game.Tournament/Screens/SetupScreen.cs index 9f8f81aa80..da91fbba04 100644 --- a/osu.Game.Tournament/Screens/SetupScreen.cs +++ b/osu.Game.Tournament/Screens/SetupScreen.cs @@ -15,7 +15,6 @@ using osu.Game.Online.API; using osu.Game.Overlays; using osu.Game.Rulesets; using osu.Game.Tournament.IPC; -using osu.Framework.Platform; using osu.Game.Tournament.Models; using osuTK; using osuTK.Graphics; @@ -43,12 +42,6 @@ namespace osu.Game.Tournament.Screens private Bindable windowSize; - [Resolved] - private Storage storage { get; set; } - - [Resolved] - private StableInfo stableInfo { get; set; } - [BackgroundDependencyLoader] private void load(FrameworkConfigManager frameworkConfig) { @@ -73,6 +66,7 @@ namespace osu.Game.Tournament.Screens private void reload() { var fileBasedIpc = ipc as FileBasedIPC; + StableInfo stableInfo = fileBasedIpc?.GetStableInfo(); fillFlow.Children = new Drawable[] { new ActionableInfo @@ -81,13 +75,13 @@ namespace osu.Game.Tournament.Screens ButtonText = "Change source", Action = () => { - stableInfo.StablePath.BindValueChanged(_ => + stableInfo?.StablePath.BindValueChanged(_ => { Schedule(reload); }); sceneManager?.SetScreen(new StablePathSelectScreen()); }, - Value = fileBasedIpc?.IPCStorage?.GetFullPath(string.Empty) ?? "Not found", + Value = fileBasedIpc?.IPCStorage.GetFullPath(string.Empty) ?? "Not found", Failing = fileBasedIpc?.IPCStorage == null, Description = "The osu!stable installation which is currently being used as a data source. If a source is not found, make sure you have created an empty ipc.txt in your stable cutting-edge installation." }, diff --git a/osu.Game.Tournament/Screens/StablePathSelectScreen.cs b/osu.Game.Tournament/Screens/StablePathSelectScreen.cs index eace3c78d5..2e1f0180a9 100644 --- a/osu.Game.Tournament/Screens/StablePathSelectScreen.cs +++ b/osu.Game.Tournament/Screens/StablePathSelectScreen.cs @@ -8,7 +8,6 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Logging; using osu.Framework.Platform; -using osu.Game.Tournament.Models; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; @@ -24,9 +23,6 @@ namespace osu.Game.Tournament.Screens { private DirectorySelector directorySelector; - [Resolved] - private StableInfo stableInfo { get; set; } - [Resolved] private MatchIPCInfo ipc { get; set; } @@ -38,7 +34,7 @@ namespace osu.Game.Tournament.Screens [BackgroundDependencyLoader(true)] private void load(Storage storage, OsuColour colours) { - var initialPath = new DirectoryInfo(storage.GetFullPath(stableInfo.StablePath.Value ?? string.Empty)).Parent?.FullName; + var initialPath = new DirectoryInfo(storage.GetFullPath(string.Empty)).Parent?.FullName; AddRangeInternal(new Drawable[] { @@ -131,7 +127,7 @@ namespace osu.Game.Tournament.Screens protected virtual void ChangePath(Storage storage) { var target = directorySelector.CurrentDirectory.Value.FullName; - stableInfo.StablePath.Value = target; + var fileBasedIpc = ipc as FileBasedIPC; Logger.Log($"Changing Stable CE location to {target}"); if (!FileBasedIPC.CheckExists(target)) @@ -143,7 +139,7 @@ namespace osu.Game.Tournament.Screens return; } - var fileBasedIpc = ipc as FileBasedIPC; + fileBasedIpc?.SaveStableConfig(target); fileBasedIpc?.LocateStableStorage(); sceneManager?.SetScreen(typeof(SetupScreen)); } diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index dcfe646390..85db9e61fb 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -43,7 +43,6 @@ namespace osu.Game.Tournament private Bindable windowSize; private FileBasedIPC ipc; - private StableInfo stableInfo; private Drawable heightWarning; @@ -72,7 +71,6 @@ namespace osu.Game.Tournament }), true); readBracket(); - readStableConfig(); ladder.CurrentMatch.Value = ladder.Matches.FirstOrDefault(p => p.Current.Value); @@ -143,23 +141,6 @@ namespace osu.Game.Tournament }); } - private void readStableConfig() - { - if (stableInfo == null) - stableInfo = new StableInfo(); - - if (storage.Exists(FileBasedIPC.STABLE_CONFIG)) - { - using (Stream stream = storage.GetStream(FileBasedIPC.STABLE_CONFIG, FileAccess.Read, FileMode.Open)) - using (var sr = new StreamReader(stream)) - { - stableInfo = JsonConvert.DeserializeObject(sr.ReadToEnd()); - } - } - - dependencies.Cache(stableInfo); - } - private void readBracket() { if (storage.Exists(bracket_filename)) From ce360a960f2d0d876a7c424baac0cd202edc336c Mon Sep 17 00:00:00 2001 From: Shivam Date: Sun, 31 May 2020 16:50:13 +0200 Subject: [PATCH 25/59] use GameHost's GetStorage instead of local storage This will now get the IPC Path again as the default path if one is present, else it will fall back to osu! lazer's base path. --- osu.Game.Tournament/Screens/StablePathSelectScreen.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tournament/Screens/StablePathSelectScreen.cs b/osu.Game.Tournament/Screens/StablePathSelectScreen.cs index 2e1f0180a9..50db0afa66 100644 --- a/osu.Game.Tournament/Screens/StablePathSelectScreen.cs +++ b/osu.Game.Tournament/Screens/StablePathSelectScreen.cs @@ -31,10 +31,14 @@ namespace osu.Game.Tournament.Screens [Resolved(canBeNull: true)] private TournamentSceneManager sceneManager { get; set; } + [Resolved] + private GameHost host { get; set; } + [BackgroundDependencyLoader(true)] private void load(Storage storage, OsuColour colours) { - var initialPath = new DirectoryInfo(storage.GetFullPath(string.Empty)).Parent?.FullName; + var fileBasedIpc = ipc as FileBasedIPC; + var initialPath = new DirectoryInfo(host.GetStorage(fileBasedIpc?.GetStableInfo().StablePath.Value).GetFullPath(string.Empty) ?? storage.GetFullPath(string.Empty)).Parent?.FullName; AddRangeInternal(new Drawable[] { From 33d731644c092f7164687b1ceeed6ec3145bae4b Mon Sep 17 00:00:00 2001 From: Shivam Date: Sun, 31 May 2020 17:35:53 +0200 Subject: [PATCH 26/59] Fix test crashing: NullReferenceException --- osu.Game.Tournament/Screens/SetupScreen.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tournament/Screens/SetupScreen.cs b/osu.Game.Tournament/Screens/SetupScreen.cs index da91fbba04..19ac84dea3 100644 --- a/osu.Game.Tournament/Screens/SetupScreen.cs +++ b/osu.Game.Tournament/Screens/SetupScreen.cs @@ -81,7 +81,7 @@ namespace osu.Game.Tournament.Screens }); sceneManager?.SetScreen(new StablePathSelectScreen()); }, - Value = fileBasedIpc?.IPCStorage.GetFullPath(string.Empty) ?? "Not found", + Value = fileBasedIpc?.IPCStorage?.GetFullPath(string.Empty) ?? "Not found", Failing = fileBasedIpc?.IPCStorage == null, Description = "The osu!stable installation which is currently being used as a data source. If a source is not found, make sure you have created an empty ipc.txt in your stable cutting-edge installation." }, From fea5c8460a45026fbe667d780d484863437e804c Mon Sep 17 00:00:00 2001 From: Shivam Date: Mon, 1 Jun 2020 22:50:24 +0200 Subject: [PATCH 27/59] Fixed path is empty exception Also converted method to property get, private set --- osu.Game.Tournament/IPC/FileBasedIPC.cs | 20 +++++++++---------- osu.Game.Tournament/Screens/SetupScreen.cs | 2 +- .../Screens/StablePathSelectScreen.cs | 7 ++++++- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/osu.Game.Tournament/IPC/FileBasedIPC.cs b/osu.Game.Tournament/IPC/FileBasedIPC.cs index 4ec9d2012a..44a010e506 100644 --- a/osu.Game.Tournament/IPC/FileBasedIPC.cs +++ b/osu.Game.Tournament/IPC/FileBasedIPC.cs @@ -37,7 +37,7 @@ namespace osu.Game.Tournament.IPC private int lastBeatmapId; private ScheduledDelegate scheduled; - private StableInfo stableInfo; + public StableInfo StableInfo { get; private set; } public const string STABLE_CONFIG = "tournament/stable.json"; @@ -160,12 +160,10 @@ namespace osu.Game.Tournament.IPC public static bool CheckExists(string p) => File.Exists(Path.Combine(p, "ipc.txt")); - public StableInfo GetStableInfo() => stableInfo; - private string findStablePath() { if (!string.IsNullOrEmpty(readStableConfig())) - return stableInfo.StablePath.Value; + return StableInfo.StablePath.Value; string stableInstallPath = string.Empty; @@ -186,7 +184,7 @@ namespace osu.Game.Tournament.IPC if (stableInstallPath != null) { SaveStableConfig(stableInstallPath); - return stableInstallPath; + return null; } } @@ -200,12 +198,12 @@ namespace osu.Game.Tournament.IPC public void SaveStableConfig(string path) { - stableInfo.StablePath.Value = path; + StableInfo.StablePath.Value = path; using (var stream = tournamentStorage.GetStream(STABLE_CONFIG, FileAccess.Write, FileMode.Create)) using (var sw = new StreamWriter(stream)) { - sw.Write(JsonConvert.SerializeObject(stableInfo, + sw.Write(JsonConvert.SerializeObject(StableInfo, new JsonSerializerSettings { Formatting = Formatting.Indented, @@ -217,18 +215,18 @@ namespace osu.Game.Tournament.IPC private string readStableConfig() { - if (stableInfo == null) - stableInfo = new StableInfo(); + if (StableInfo == null) + StableInfo = new StableInfo(); if (tournamentStorage.Exists(FileBasedIPC.STABLE_CONFIG)) { using (Stream stream = tournamentStorage.GetStream(FileBasedIPC.STABLE_CONFIG, FileAccess.Read, FileMode.Open)) using (var sr = new StreamReader(stream)) { - stableInfo = JsonConvert.DeserializeObject(sr.ReadToEnd()); + StableInfo = JsonConvert.DeserializeObject(sr.ReadToEnd()); } - return stableInfo.StablePath.Value; + return StableInfo.StablePath.Value; } return null; diff --git a/osu.Game.Tournament/Screens/SetupScreen.cs b/osu.Game.Tournament/Screens/SetupScreen.cs index 19ac84dea3..db7669184f 100644 --- a/osu.Game.Tournament/Screens/SetupScreen.cs +++ b/osu.Game.Tournament/Screens/SetupScreen.cs @@ -66,7 +66,7 @@ namespace osu.Game.Tournament.Screens private void reload() { var fileBasedIpc = ipc as FileBasedIPC; - StableInfo stableInfo = fileBasedIpc?.GetStableInfo(); + StableInfo stableInfo = fileBasedIpc?.StableInfo; fillFlow.Children = new Drawable[] { new ActionableInfo diff --git a/osu.Game.Tournament/Screens/StablePathSelectScreen.cs b/osu.Game.Tournament/Screens/StablePathSelectScreen.cs index 50db0afa66..fee2696c4c 100644 --- a/osu.Game.Tournament/Screens/StablePathSelectScreen.cs +++ b/osu.Game.Tournament/Screens/StablePathSelectScreen.cs @@ -38,7 +38,12 @@ namespace osu.Game.Tournament.Screens private void load(Storage storage, OsuColour colours) { var fileBasedIpc = ipc as FileBasedIPC; - var initialPath = new DirectoryInfo(host.GetStorage(fileBasedIpc?.GetStableInfo().StablePath.Value).GetFullPath(string.Empty) ?? storage.GetFullPath(string.Empty)).Parent?.FullName; + var initialPath = new DirectoryInfo(storage.GetFullPath(string.Empty)).Parent?.FullName; + + if (!string.IsNullOrEmpty(fileBasedIpc?.StableInfo.StablePath.Value)) + { + initialPath = new DirectoryInfo(host.GetStorage(fileBasedIpc.StableInfo.StablePath.Value).GetFullPath(string.Empty)).Parent?.FullName; + } AddRangeInternal(new Drawable[] { From 7e5db5e933aea2b39dbf7faf769f5e1ffba9322b Mon Sep 17 00:00:00 2001 From: Shivam Date: Wed, 3 Jun 2020 23:49:06 +0200 Subject: [PATCH 28/59] Apply review suggestions --- .../Components/IPCErrorDialog.cs | 2 +- osu.Game.Tournament/IPC/FileBasedIPC.cs | 22 ++++++++++++------- .../Screens/StablePathSelectScreen.cs | 4 +--- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/osu.Game.Tournament/Components/IPCErrorDialog.cs b/osu.Game.Tournament/Components/IPCErrorDialog.cs index 07fd0ac973..dc039cd3bc 100644 --- a/osu.Game.Tournament/Components/IPCErrorDialog.cs +++ b/osu.Game.Tournament/Components/IPCErrorDialog.cs @@ -18,7 +18,7 @@ namespace osu.Game.Tournament.Components new PopupDialogOkButton { Text = @"Alright.", - Action = () => { Expire(); } + Action = () => Expire() } }; } diff --git a/osu.Game.Tournament/IPC/FileBasedIPC.cs b/osu.Game.Tournament/IPC/FileBasedIPC.cs index 44a010e506..aad44cd385 100644 --- a/osu.Game.Tournament/IPC/FileBasedIPC.cs +++ b/osu.Game.Tournament/IPC/FileBasedIPC.cs @@ -158,7 +158,7 @@ namespace osu.Game.Tournament.IPC return IPCStorage; } - public static bool CheckExists(string p) => File.Exists(Path.Combine(p, "ipc.txt")); + private static bool ipcFileExistsInDirectory(string p) => File.Exists(Path.Combine(p, "ipc.txt")); private string findStablePath() { @@ -183,8 +183,8 @@ namespace osu.Game.Tournament.IPC if (stableInstallPath != null) { - SaveStableConfig(stableInstallPath); - return null; + SetIPCLocation(stableInstallPath); + return stableInstallPath; } } @@ -196,8 +196,11 @@ namespace osu.Game.Tournament.IPC } } - public void SaveStableConfig(string path) + public bool SetIPCLocation(string path) { + if (!ipcFileExistsInDirectory(path)) + return false; + StableInfo.StablePath.Value = path; using (var stream = tournamentStorage.GetStream(STABLE_CONFIG, FileAccess.Write, FileMode.Create)) @@ -211,6 +214,9 @@ namespace osu.Game.Tournament.IPC DefaultValueHandling = DefaultValueHandling.Ignore, })); } + + LocateStableStorage(); + return true; } private string readStableConfig() @@ -239,7 +245,7 @@ namespace osu.Game.Tournament.IPC Logger.Log("Trying to find stable with environment variables"); string stableInstallPath = Environment.GetEnvironmentVariable("OSU_STABLE_PATH"); - if (CheckExists(stableInstallPath)) + if (ipcFileExistsInDirectory(stableInstallPath)) return stableInstallPath; } catch @@ -254,7 +260,7 @@ namespace osu.Game.Tournament.IPC Logger.Log("Trying to find stable in %LOCALAPPDATA%"); string stableInstallPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), @"osu!"); - if (CheckExists(stableInstallPath)) + if (ipcFileExistsInDirectory(stableInstallPath)) return stableInstallPath; return null; @@ -265,7 +271,7 @@ namespace osu.Game.Tournament.IPC Logger.Log("Trying to find stable in dotfolders"); string stableInstallPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".osu"); - if (CheckExists(stableInstallPath)) + if (ipcFileExistsInDirectory(stableInstallPath)) return stableInstallPath; return null; @@ -280,7 +286,7 @@ namespace osu.Game.Tournament.IPC using (RegistryKey key = Registry.ClassesRoot.OpenSubKey("osu")) stableInstallPath = key?.OpenSubKey(@"shell\open\command")?.GetValue(string.Empty).ToString().Split('"')[1].Replace("osu!.exe", ""); - if (CheckExists(stableInstallPath)) + if (ipcFileExistsInDirectory(stableInstallPath)) return stableInstallPath; return null; diff --git a/osu.Game.Tournament/Screens/StablePathSelectScreen.cs b/osu.Game.Tournament/Screens/StablePathSelectScreen.cs index fee2696c4c..ad0c06e4f9 100644 --- a/osu.Game.Tournament/Screens/StablePathSelectScreen.cs +++ b/osu.Game.Tournament/Screens/StablePathSelectScreen.cs @@ -139,7 +139,7 @@ namespace osu.Game.Tournament.Screens var fileBasedIpc = ipc as FileBasedIPC; Logger.Log($"Changing Stable CE location to {target}"); - if (!FileBasedIPC.CheckExists(target)) + if (!fileBasedIpc?.SetIPCLocation(target) ?? false) { overlay = new DialogOverlay(); overlay.Push(new IPCErrorDialog("This is an invalid IPC Directory", "Select a directory that contains an osu! stable cutting edge installation and make sure it has an empty ipc.txt file in it.")); @@ -148,8 +148,6 @@ namespace osu.Game.Tournament.Screens return; } - fileBasedIpc?.SaveStableConfig(target); - fileBasedIpc?.LocateStableStorage(); sceneManager?.SetScreen(typeof(SetupScreen)); } From 1cd96b80021c39e82e091808a89ac15c2426fc36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 13 Jun 2020 15:05:52 +0200 Subject: [PATCH 29/59] Rework StableInfo into a DI'd data structure --- osu.Game.Tournament/IPC/FileBasedIPC.cs | 48 ++++--------------- osu.Game.Tournament/Models/StableInfo.cs | 43 ++++++++++++++++- osu.Game.Tournament/Screens/SetupScreen.cs | 14 ++---- .../Screens/StablePathSelectScreen.cs | 20 ++++---- osu.Game.Tournament/TournamentGameBase.cs | 2 + 5 files changed, 67 insertions(+), 60 deletions(-) diff --git a/osu.Game.Tournament/IPC/FileBasedIPC.cs b/osu.Game.Tournament/IPC/FileBasedIPC.cs index 16f2b0b1fd..a9b39c7ba2 100644 --- a/osu.Game.Tournament/IPC/FileBasedIPC.cs +++ b/osu.Game.Tournament/IPC/FileBasedIPC.cs @@ -5,7 +5,6 @@ using System; using System.IO; using System.Linq; using System.Collections.Generic; -using Newtonsoft.Json; using Microsoft.Win32; using osu.Framework.Allocation; using osu.Framework.Logging; @@ -34,14 +33,13 @@ namespace osu.Game.Tournament.IPC [Resolved] private LadderInfo ladder { get; set; } + [Resolved] + private StableInfo stableInfo { get; set; } + private int lastBeatmapId; private ScheduledDelegate scheduled; private GetBeatmapRequest beatmapLookupRequest; - public StableInfo StableInfo { get; private set; } - - public const string STABLE_CONFIG = "tournament/stable.json"; - public Storage IPCStorage { get; private set; } [Resolved] @@ -165,8 +163,8 @@ namespace osu.Game.Tournament.IPC private string findStablePath() { - if (!string.IsNullOrEmpty(readStableConfig())) - return StableInfo.StablePath.Value; + if (!string.IsNullOrEmpty(stableInfo.StablePath)) + return stableInfo.StablePath; string stableInstallPath = string.Empty; @@ -204,43 +202,13 @@ namespace osu.Game.Tournament.IPC if (!ipcFileExistsInDirectory(path)) return false; - StableInfo.StablePath.Value = path; - - using (var stream = tournamentStorage.GetStream(STABLE_CONFIG, FileAccess.Write, FileMode.Create)) - using (var sw = new StreamWriter(stream)) - { - sw.Write(JsonConvert.SerializeObject(StableInfo, - new JsonSerializerSettings - { - Formatting = Formatting.Indented, - NullValueHandling = NullValueHandling.Ignore, - DefaultValueHandling = DefaultValueHandling.Ignore, - })); - } - + stableInfo.StablePath = path; LocateStableStorage(); + stableInfo.SaveChanges(); + return true; } - private string readStableConfig() - { - if (StableInfo == null) - StableInfo = new StableInfo(); - - if (tournamentStorage.Exists(FileBasedIPC.STABLE_CONFIG)) - { - using (Stream stream = tournamentStorage.GetStream(FileBasedIPC.STABLE_CONFIG, FileAccess.Read, FileMode.Open)) - using (var sr = new StreamReader(stream)) - { - StableInfo = JsonConvert.DeserializeObject(sr.ReadToEnd()); - } - - return StableInfo.StablePath.Value; - } - - return null; - } - private string findFromEnvVar() { try diff --git a/osu.Game.Tournament/Models/StableInfo.cs b/osu.Game.Tournament/Models/StableInfo.cs index 4818842151..1faf6beaff 100644 --- a/osu.Game.Tournament/Models/StableInfo.cs +++ b/osu.Game.Tournament/Models/StableInfo.cs @@ -2,7 +2,9 @@ // See the LICENCE file in the repository root for full licence text. using System; -using osu.Framework.Bindables; +using System.IO; +using Newtonsoft.Json; +using osu.Framework.Platform; namespace osu.Game.Tournament.Models { @@ -12,6 +14,43 @@ namespace osu.Game.Tournament.Models [Serializable] public class StableInfo { - public Bindable StablePath = new Bindable(string.Empty); + public string StablePath { get; set; } + + public event Action OnStableInfoSaved; + + private const string config_path = "tournament/stable.json"; + + private readonly Storage storage; + + public StableInfo(Storage storage) + { + this.storage = storage; + + if (!storage.Exists(config_path)) + return; + + using (Stream stream = storage.GetStream(config_path, FileAccess.Read, FileMode.Open)) + using (var sr = new StreamReader(stream)) + { + JsonConvert.PopulateObject(sr.ReadToEnd(), this); + } + } + + public void SaveChanges() + { + using (var stream = storage.GetStream(config_path, FileAccess.Write, FileMode.Create)) + using (var sw = new StreamWriter(stream)) + { + sw.Write(JsonConvert.SerializeObject(this, + new JsonSerializerSettings + { + Formatting = Formatting.Indented, + NullValueHandling = NullValueHandling.Ignore, + DefaultValueHandling = DefaultValueHandling.Ignore, + })); + } + + OnStableInfoSaved?.Invoke(); + } } } diff --git a/osu.Game.Tournament/Screens/SetupScreen.cs b/osu.Game.Tournament/Screens/SetupScreen.cs index 503a2487da..98bc292901 100644 --- a/osu.Game.Tournament/Screens/SetupScreen.cs +++ b/osu.Game.Tournament/Screens/SetupScreen.cs @@ -31,6 +31,9 @@ namespace osu.Game.Tournament.Screens [Resolved] private MatchIPCInfo ipc { get; set; } + [Resolved] + private StableInfo stableInfo { get; set; } + [Resolved] private IAPIProvider api { get; set; } @@ -57,6 +60,7 @@ namespace osu.Game.Tournament.Screens }; api.LocalUser.BindValueChanged(_ => Schedule(reload)); + stableInfo.OnStableInfoSaved += () => Schedule(reload); reload(); } @@ -66,21 +70,13 @@ namespace osu.Game.Tournament.Screens private void reload() { var fileBasedIpc = ipc as FileBasedIPC; - StableInfo stableInfo = fileBasedIpc?.StableInfo; fillFlow.Children = new Drawable[] { new ActionableInfo { Label = "Current IPC source", ButtonText = "Change source", - Action = () => - { - stableInfo?.StablePath.BindValueChanged(_ => - { - Schedule(reload); - }); - sceneManager?.SetScreen(new StablePathSelectScreen()); - }, + Action = () => sceneManager?.SetScreen(new StablePathSelectScreen()), Value = fileBasedIpc?.IPCStorage?.GetFullPath(string.Empty) ?? "Not found", Failing = fileBasedIpc?.IPCStorage == null, Description = "The osu!stable installation which is currently being used as a data source. If a source is not found, make sure you have created an empty ipc.txt in your stable cutting-edge installation." diff --git a/osu.Game.Tournament/Screens/StablePathSelectScreen.cs b/osu.Game.Tournament/Screens/StablePathSelectScreen.cs index ad0c06e4f9..816f0ed4b8 100644 --- a/osu.Game.Tournament/Screens/StablePathSelectScreen.cs +++ b/osu.Game.Tournament/Screens/StablePathSelectScreen.cs @@ -15,34 +15,36 @@ using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Overlays; using osu.Game.Tournament.IPC; using osu.Game.Tournament.Components; +using osu.Game.Tournament.Models; using osuTK; namespace osu.Game.Tournament.Screens { public class StablePathSelectScreen : TournamentScreen { - private DirectorySelector directorySelector; - [Resolved] - private MatchIPCInfo ipc { get; set; } - - private DialogOverlay overlay; + private GameHost host { get; set; } [Resolved(canBeNull: true)] private TournamentSceneManager sceneManager { get; set; } [Resolved] - private GameHost host { get; set; } + private MatchIPCInfo ipc { get; set; } + + [Resolved] + private StableInfo stableInfo { get; set; } + + private DirectorySelector directorySelector; + private DialogOverlay overlay; [BackgroundDependencyLoader(true)] private void load(Storage storage, OsuColour colours) { - var fileBasedIpc = ipc as FileBasedIPC; var initialPath = new DirectoryInfo(storage.GetFullPath(string.Empty)).Parent?.FullName; - if (!string.IsNullOrEmpty(fileBasedIpc?.StableInfo.StablePath.Value)) + if (!string.IsNullOrEmpty(stableInfo.StablePath)) { - initialPath = new DirectoryInfo(host.GetStorage(fileBasedIpc.StableInfo.StablePath.Value).GetFullPath(string.Empty)).Parent?.FullName; + initialPath = new DirectoryInfo(host.GetStorage(stableInfo.StablePath).GetFullPath(string.Empty)).Parent?.FullName; } AddRangeInternal(new Drawable[] diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index 718c8ee644..5fc1d03f6d 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -53,6 +53,8 @@ namespace osu.Game.Tournament ladder.CurrentMatch.Value = ladder.Matches.FirstOrDefault(p => p.Current.Value); + dependencies.CacheAs(new StableInfo(storage)); + dependencies.CacheAs(ipc = new FileBasedIPC()); Add(ipc); } From 586d5791e029d2de9a779fdbf9d9c12af3cfab28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 13 Jun 2020 15:07:21 +0200 Subject: [PATCH 30/59] Remove unused argument --- .../Screens/TestSceneStablePathSelectScreen.cs | 3 +-- osu.Game.Tournament/Screens/StablePathSelectScreen.cs | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneStablePathSelectScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneStablePathSelectScreen.cs index ce0626dd0f..6e63b2d799 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneStablePathSelectScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneStablePathSelectScreen.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using osu.Game.Tournament.Screens; -using osu.Framework.Platform; namespace osu.Game.Tournament.Tests.Screens { @@ -15,7 +14,7 @@ namespace osu.Game.Tournament.Tests.Screens private class StablePathSelectTestScreen : StablePathSelectScreen { - protected override void ChangePath(Storage storage) + protected override void ChangePath() { Expire(); } diff --git a/osu.Game.Tournament/Screens/StablePathSelectScreen.cs b/osu.Game.Tournament/Screens/StablePathSelectScreen.cs index 816f0ed4b8..a830cbe4b9 100644 --- a/osu.Game.Tournament/Screens/StablePathSelectScreen.cs +++ b/osu.Game.Tournament/Screens/StablePathSelectScreen.cs @@ -108,7 +108,7 @@ namespace osu.Game.Tournament.Screens Origin = Anchor.Centre, Width = 300, Text = "Select stable path", - Action = () => ChangePath(storage) + Action = ChangePath }, new TriangleButton { @@ -135,7 +135,7 @@ namespace osu.Game.Tournament.Screens }); } - protected virtual void ChangePath(Storage storage) + protected virtual void ChangePath() { var target = directorySelector.CurrentDirectory.Value.FullName; var fileBasedIpc = ipc as FileBasedIPC; From 992aa0041e3933dcf8ded8b9778cb76bc5c02ff1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 13 Jun 2020 15:27:46 +0200 Subject: [PATCH 31/59] Allow auto-detect to work after choosing manually --- osu.Game.Tournament/IPC/FileBasedIPC.cs | 64 +++++++++++-------- .../Screens/StablePathSelectScreen.cs | 3 +- 2 files changed, 38 insertions(+), 29 deletions(-) diff --git a/osu.Game.Tournament/IPC/FileBasedIPC.cs b/osu.Game.Tournament/IPC/FileBasedIPC.cs index a9b39c7ba2..01466231a6 100644 --- a/osu.Game.Tournament/IPC/FileBasedIPC.cs +++ b/osu.Game.Tournament/IPC/FileBasedIPC.cs @@ -5,6 +5,7 @@ using System; using System.IO; using System.Linq; using System.Collections.Generic; +using JetBrains.Annotations; using Microsoft.Win32; using osu.Framework.Allocation; using osu.Framework.Logging; @@ -21,6 +22,8 @@ namespace osu.Game.Tournament.IPC { public class FileBasedIPC : MatchIPCInfo { + public Storage IPCStorage { get; private set; } + [Resolved] protected IAPIProvider API { get; private set; } @@ -36,22 +39,22 @@ namespace osu.Game.Tournament.IPC [Resolved] private StableInfo stableInfo { get; set; } + [Resolved] + private Storage tournamentStorage { get; set; } + private int lastBeatmapId; private ScheduledDelegate scheduled; private GetBeatmapRequest beatmapLookupRequest; - public Storage IPCStorage { get; private set; } - - [Resolved] - private Storage tournamentStorage { get; set; } - [BackgroundDependencyLoader] private void load() { - LocateStableStorage(); + var stablePath = stableInfo.StablePath ?? findStablePath(); + initialiseIPCStorage(stablePath); } - public Storage LocateStableStorage() + [CanBeNull] + private Storage initialiseIPCStorage(string path) { scheduled?.Cancel(); @@ -59,8 +62,6 @@ namespace osu.Game.Tournament.IPC try { - var path = findStablePath(); - if (string.IsNullOrEmpty(path)) return null; @@ -159,13 +160,37 @@ namespace osu.Game.Tournament.IPC return IPCStorage; } + public bool SetIPCLocation(string path) + { + if (!ipcFileExistsInDirectory(path)) + return false; + + var newStorage = initialiseIPCStorage(stableInfo.StablePath = path); + if (newStorage == null) + return false; + + stableInfo.SaveChanges(); + return true; + } + + public bool AutoDetectIPCLocation() + { + var autoDetectedPath = findStablePath(); + if (string.IsNullOrEmpty(autoDetectedPath)) + return false; + + var newStorage = initialiseIPCStorage(stableInfo.StablePath = autoDetectedPath); + if (newStorage == null) + return false; + + stableInfo.SaveChanges(); + return true; + } + private static bool ipcFileExistsInDirectory(string p) => File.Exists(Path.Combine(p, "ipc.txt")); private string findStablePath() { - if (!string.IsNullOrEmpty(stableInfo.StablePath)) - return stableInfo.StablePath; - string stableInstallPath = string.Empty; try @@ -183,10 +208,7 @@ namespace osu.Game.Tournament.IPC stableInstallPath = r.Invoke(); if (stableInstallPath != null) - { - SetIPCLocation(stableInstallPath); return stableInstallPath; - } } return null; @@ -197,18 +219,6 @@ namespace osu.Game.Tournament.IPC } } - public bool SetIPCLocation(string path) - { - if (!ipcFileExistsInDirectory(path)) - return false; - - stableInfo.StablePath = path; - LocateStableStorage(); - stableInfo.SaveChanges(); - - return true; - } - private string findFromEnvVar() { try diff --git a/osu.Game.Tournament/Screens/StablePathSelectScreen.cs b/osu.Game.Tournament/Screens/StablePathSelectScreen.cs index a830cbe4b9..2a54dffc7c 100644 --- a/osu.Game.Tournament/Screens/StablePathSelectScreen.cs +++ b/osu.Game.Tournament/Screens/StablePathSelectScreen.cs @@ -156,9 +156,8 @@ namespace osu.Game.Tournament.Screens protected virtual void AutoDetect() { var fileBasedIpc = ipc as FileBasedIPC; - fileBasedIpc?.LocateStableStorage(); - if (fileBasedIpc?.IPCStorage == null) + if (!fileBasedIpc?.AutoDetectIPCLocation() ?? true) { overlay = new DialogOverlay(); overlay.Push(new IPCErrorDialog("Failed to auto detect", "An osu! stable cutting-edge installation could not be auto detected.\nPlease try and manually point to the directory.")); From 34cd9f7a699d62dd339c9a18bb95fefeddab0de1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 13 Jun 2020 15:32:30 +0200 Subject: [PATCH 32/59] Streamline autodetect & manual set path --- osu.Game.Tournament/IPC/FileBasedIPC.cs | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/osu.Game.Tournament/IPC/FileBasedIPC.cs b/osu.Game.Tournament/IPC/FileBasedIPC.cs index 01466231a6..de9df3ca35 100644 --- a/osu.Game.Tournament/IPC/FileBasedIPC.cs +++ b/osu.Game.Tournament/IPC/FileBasedIPC.cs @@ -162,7 +162,7 @@ namespace osu.Game.Tournament.IPC public bool SetIPCLocation(string path) { - if (!ipcFileExistsInDirectory(path)) + if (path == null || !ipcFileExistsInDirectory(path)) return false; var newStorage = initialiseIPCStorage(stableInfo.StablePath = path); @@ -173,22 +173,11 @@ namespace osu.Game.Tournament.IPC return true; } - public bool AutoDetectIPCLocation() - { - var autoDetectedPath = findStablePath(); - if (string.IsNullOrEmpty(autoDetectedPath)) - return false; - - var newStorage = initialiseIPCStorage(stableInfo.StablePath = autoDetectedPath); - if (newStorage == null) - return false; - - stableInfo.SaveChanges(); - return true; - } + public bool AutoDetectIPCLocation() => SetIPCLocation(findStablePath()); private static bool ipcFileExistsInDirectory(string p) => File.Exists(Path.Combine(p, "ipc.txt")); + [CanBeNull] private string findStablePath() { string stableInstallPath = string.Empty; From e0518fd451ac9aebd3b4506ada28eb202e55cf25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 13 Jun 2020 15:38:29 +0200 Subject: [PATCH 33/59] Fix silent failure --- osu.Game.Tournament/Screens/StablePathSelectScreen.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tournament/Screens/StablePathSelectScreen.cs b/osu.Game.Tournament/Screens/StablePathSelectScreen.cs index 2a54dffc7c..0b9900c0d4 100644 --- a/osu.Game.Tournament/Screens/StablePathSelectScreen.cs +++ b/osu.Game.Tournament/Screens/StablePathSelectScreen.cs @@ -141,7 +141,7 @@ namespace osu.Game.Tournament.Screens var fileBasedIpc = ipc as FileBasedIPC; Logger.Log($"Changing Stable CE location to {target}"); - if (!fileBasedIpc?.SetIPCLocation(target) ?? false) + if (!fileBasedIpc?.SetIPCLocation(target) ?? true) { overlay = new DialogOverlay(); overlay.Push(new IPCErrorDialog("This is an invalid IPC Directory", "Select a directory that contains an osu! stable cutting edge installation and make sure it has an empty ipc.txt file in it.")); From 5dd47bf393b5116b9077ef4aeea3942ca5a0d766 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 13 Jun 2020 16:01:00 +0200 Subject: [PATCH 34/59] Remove unnecessary members --- osu.Game.Tournament/IPC/FileBasedIPC.cs | 3 --- osu.Game.Tournament/Screens/StablePathSelectScreen.cs | 9 --------- 2 files changed, 12 deletions(-) diff --git a/osu.Game.Tournament/IPC/FileBasedIPC.cs b/osu.Game.Tournament/IPC/FileBasedIPC.cs index de9df3ca35..d52a2b6445 100644 --- a/osu.Game.Tournament/IPC/FileBasedIPC.cs +++ b/osu.Game.Tournament/IPC/FileBasedIPC.cs @@ -39,9 +39,6 @@ namespace osu.Game.Tournament.IPC [Resolved] private StableInfo stableInfo { get; set; } - [Resolved] - private Storage tournamentStorage { get; set; } - private int lastBeatmapId; private ScheduledDelegate scheduled; private GetBeatmapRequest beatmapLookupRequest; diff --git a/osu.Game.Tournament/Screens/StablePathSelectScreen.cs b/osu.Game.Tournament/Screens/StablePathSelectScreen.cs index 0b9900c0d4..958c3ef822 100644 --- a/osu.Game.Tournament/Screens/StablePathSelectScreen.cs +++ b/osu.Game.Tournament/Screens/StablePathSelectScreen.cs @@ -15,7 +15,6 @@ using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Overlays; using osu.Game.Tournament.IPC; using osu.Game.Tournament.Components; -using osu.Game.Tournament.Models; using osuTK; namespace osu.Game.Tournament.Screens @@ -31,9 +30,6 @@ namespace osu.Game.Tournament.Screens [Resolved] private MatchIPCInfo ipc { get; set; } - [Resolved] - private StableInfo stableInfo { get; set; } - private DirectorySelector directorySelector; private DialogOverlay overlay; @@ -42,11 +38,6 @@ namespace osu.Game.Tournament.Screens { var initialPath = new DirectoryInfo(storage.GetFullPath(string.Empty)).Parent?.FullName; - if (!string.IsNullOrEmpty(stableInfo.StablePath)) - { - initialPath = new DirectoryInfo(host.GetStorage(stableInfo.StablePath).GetFullPath(string.Empty)).Parent?.FullName; - } - AddRangeInternal(new Drawable[] { new Container From 2cadab8d29a3e5f30fbc9676f1a23d3fdd6df682 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 13 Jun 2020 16:20:59 +0200 Subject: [PATCH 35/59] Add xmldoc --- osu.Game.Tournament/IPC/FileBasedIPC.cs | 10 ++++++++++ osu.Game.Tournament/Models/StableInfo.cs | 6 ++++++ 2 files changed, 16 insertions(+) diff --git a/osu.Game.Tournament/IPC/FileBasedIPC.cs b/osu.Game.Tournament/IPC/FileBasedIPC.cs index d52a2b6445..681839ebc4 100644 --- a/osu.Game.Tournament/IPC/FileBasedIPC.cs +++ b/osu.Game.Tournament/IPC/FileBasedIPC.cs @@ -157,6 +157,11 @@ namespace osu.Game.Tournament.IPC return IPCStorage; } + /// + /// Manually sets the path to the directory used for inter-process communication with a cutting-edge install. + /// + /// Path to the IPC directory + /// Whether the supplied path was a valid IPC directory. public bool SetIPCLocation(string path) { if (path == null || !ipcFileExistsInDirectory(path)) @@ -170,6 +175,11 @@ namespace osu.Game.Tournament.IPC return true; } + /// + /// Tries to automatically detect the path to the directory used for inter-process communication + /// with a cutting-edge install. + /// + /// Whether an IPC directory was successfully auto-detected. public bool AutoDetectIPCLocation() => SetIPCLocation(findStablePath()); private static bool ipcFileExistsInDirectory(string p) => File.Exists(Path.Combine(p, "ipc.txt")); diff --git a/osu.Game.Tournament/Models/StableInfo.cs b/osu.Game.Tournament/Models/StableInfo.cs index 1faf6beaff..0b0050a245 100644 --- a/osu.Game.Tournament/Models/StableInfo.cs +++ b/osu.Game.Tournament/Models/StableInfo.cs @@ -14,8 +14,14 @@ namespace osu.Game.Tournament.Models [Serializable] public class StableInfo { + /// + /// Path to the IPC directory used by the stable (cutting-edge) install. + /// public string StablePath { get; set; } + /// + /// Fired whenever stable info is successfully saved to file. + /// public event Action OnStableInfoSaved; private const string config_path = "tournament/stable.json"; From 308ec6a491a051e029e9fd3d2ee30fa03cd080bf Mon Sep 17 00:00:00 2001 From: mcendu Date: Sat, 13 Jun 2020 23:05:57 +0800 Subject: [PATCH 36/59] add extension method for mania skin config retrieval --- .../Skinning/ManiaSkinConfigExtensions.cs | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 osu.Game.Rulesets.Mania/Skinning/ManiaSkinConfigExtensions.cs diff --git a/osu.Game.Rulesets.Mania/Skinning/ManiaSkinConfigExtensions.cs b/osu.Game.Rulesets.Mania/Skinning/ManiaSkinConfigExtensions.cs new file mode 100644 index 0000000000..2e17a6bef1 --- /dev/null +++ b/osu.Game.Rulesets.Mania/Skinning/ManiaSkinConfigExtensions.cs @@ -0,0 +1,21 @@ +// 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.Bindables; +using osu.Game.Skinning; + +namespace osu.Game.Rulesets.Mania.Skinning +{ + public static class ManiaSkinConfigExtensions + { + /// + /// Retrieve a per-column-count skin configuration. + /// + /// The skin from which configuration is retrieved. + /// The value to retrieve. + /// If not null, denotes the index of the column to which the entry applies. + public static IBindable GetManiaSkinConfig(this ISkin skin, LegacyManiaSkinConfigurationLookups lookup, int? index = null) + => skin.GetConfig( + new ManiaSkinConfigurationLookup(lookup, index)); + } +} From bd7b7b50176c37cd799a560a060adf5a9f74daab Mon Sep 17 00:00:00 2001 From: mcendu Date: Sat, 13 Jun 2020 23:06:25 +0800 Subject: [PATCH 37/59] make all former LegacyManiaElement subclasses use extension method Remove LegacyManiaElement --- .../Skinning/LegacyHitTarget.cs | 8 +++--- .../Skinning/LegacyManiaColumnElement.cs | 6 ++--- .../Skinning/LegacyManiaElement.cs | 25 ------------------- .../Skinning/LegacyStageBackground.cs | 7 +++--- .../Skinning/LegacyStageForeground.cs | 5 ++-- 5 files changed, 14 insertions(+), 37 deletions(-) delete mode 100644 osu.Game.Rulesets.Mania/Skinning/LegacyManiaElement.cs diff --git a/osu.Game.Rulesets.Mania/Skinning/LegacyHitTarget.cs b/osu.Game.Rulesets.Mania/Skinning/LegacyHitTarget.cs index 40752d3f4b..d055ef3480 100644 --- a/osu.Game.Rulesets.Mania/Skinning/LegacyHitTarget.cs +++ b/osu.Game.Rulesets.Mania/Skinning/LegacyHitTarget.cs @@ -14,7 +14,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Mania.Skinning { - public class LegacyHitTarget : LegacyManiaElement + public class LegacyHitTarget : CompositeDrawable { private readonly IBindable direction = new Bindable(); @@ -28,13 +28,13 @@ namespace osu.Game.Rulesets.Mania.Skinning [BackgroundDependencyLoader] private void load(ISkinSource skin, IScrollingInfo scrollingInfo) { - string targetImage = GetManiaSkinConfig(skin, LegacyManiaSkinConfigurationLookups.HitTargetImage)?.Value + string targetImage = skin.GetManiaSkinConfig(LegacyManiaSkinConfigurationLookups.HitTargetImage)?.Value ?? "mania-stage-hint"; - bool showJudgementLine = GetManiaSkinConfig(skin, LegacyManiaSkinConfigurationLookups.ShowJudgementLine)?.Value + bool showJudgementLine = skin.GetManiaSkinConfig(LegacyManiaSkinConfigurationLookups.ShowJudgementLine)?.Value ?? true; - Color4 lineColour = GetManiaSkinConfig(skin, LegacyManiaSkinConfigurationLookups.JudgementLineColour)?.Value + Color4 lineColour = skin.GetManiaSkinConfig(LegacyManiaSkinConfigurationLookups.JudgementLineColour)?.Value ?? Color4.White; InternalChild = directionContainer = new Container diff --git a/osu.Game.Rulesets.Mania/Skinning/LegacyManiaColumnElement.cs b/osu.Game.Rulesets.Mania/Skinning/LegacyManiaColumnElement.cs index 05b731ec5d..0c46a00bed 100644 --- a/osu.Game.Rulesets.Mania/Skinning/LegacyManiaColumnElement.cs +++ b/osu.Game.Rulesets.Mania/Skinning/LegacyManiaColumnElement.cs @@ -13,7 +13,7 @@ namespace osu.Game.Rulesets.Mania.Skinning /// /// A which is placed somewhere within a . /// - public class LegacyManiaColumnElement : LegacyManiaElement + public class LegacyManiaColumnElement : CompositeDrawable { [Resolved] protected Column Column { get; private set; } @@ -42,7 +42,7 @@ namespace osu.Game.Rulesets.Mania.Skinning } } - protected override IBindable GetManiaSkinConfig(ISkin skin, LegacyManiaSkinConfigurationLookups lookup, int? index = null) - => base.GetManiaSkinConfig(skin, lookup, index ?? Column.Index); + protected IBindable GetManiaSkinConfig(ISkin skin, LegacyManiaSkinConfigurationLookups lookup, int? index = null) + => skin.GetManiaSkinConfig(lookup, index ?? Column.Index); } } diff --git a/osu.Game.Rulesets.Mania/Skinning/LegacyManiaElement.cs b/osu.Game.Rulesets.Mania/Skinning/LegacyManiaElement.cs deleted file mode 100644 index 11fdd663a1..0000000000 --- a/osu.Game.Rulesets.Mania/Skinning/LegacyManiaElement.cs +++ /dev/null @@ -1,25 +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.Bindables; -using osu.Framework.Graphics.Containers; -using osu.Game.Skinning; - -namespace osu.Game.Rulesets.Mania.Skinning -{ - /// - /// A mania legacy skin element. - /// - public class LegacyManiaElement : CompositeDrawable - { - /// - /// Retrieve a per-column-count skin configuration. - /// - /// The skin from which configuration is retrieved. - /// The value to retrieve. - /// If not null, denotes the index of the column to which the entry applies. - protected virtual IBindable GetManiaSkinConfig(ISkin skin, LegacyManiaSkinConfigurationLookups lookup, int? index = null) - => skin.GetConfig( - new ManiaSkinConfigurationLookup(lookup, index)); - } -} diff --git a/osu.Game.Rulesets.Mania/Skinning/LegacyStageBackground.cs b/osu.Game.Rulesets.Mania/Skinning/LegacyStageBackground.cs index f177284399..7f5de601ca 100644 --- a/osu.Game.Rulesets.Mania/Skinning/LegacyStageBackground.cs +++ b/osu.Game.Rulesets.Mania/Skinning/LegacyStageBackground.cs @@ -3,13 +3,14 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Game.Skinning; using osuTK; namespace osu.Game.Rulesets.Mania.Skinning { - public class LegacyStageBackground : LegacyManiaElement + public class LegacyStageBackground : CompositeDrawable { private Drawable leftSprite; private Drawable rightSprite; @@ -22,10 +23,10 @@ namespace osu.Game.Rulesets.Mania.Skinning [BackgroundDependencyLoader] private void load(ISkinSource skin) { - string leftImage = GetManiaSkinConfig(skin, LegacyManiaSkinConfigurationLookups.LeftStageImage)?.Value + string leftImage = skin.GetManiaSkinConfig(LegacyManiaSkinConfigurationLookups.LeftStageImage)?.Value ?? "mania-stage-left"; - string rightImage = GetManiaSkinConfig(skin, LegacyManiaSkinConfigurationLookups.RightStageImage)?.Value + string rightImage = skin.GetManiaSkinConfig(LegacyManiaSkinConfigurationLookups.RightStageImage)?.Value ?? "mania-stage-right"; InternalChildren = new[] diff --git a/osu.Game.Rulesets.Mania/Skinning/LegacyStageForeground.cs b/osu.Game.Rulesets.Mania/Skinning/LegacyStageForeground.cs index 9719005d54..4609fcc849 100644 --- a/osu.Game.Rulesets.Mania/Skinning/LegacyStageForeground.cs +++ b/osu.Game.Rulesets.Mania/Skinning/LegacyStageForeground.cs @@ -4,13 +4,14 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Skinning; using osuTK; namespace osu.Game.Rulesets.Mania.Skinning { - public class LegacyStageForeground : LegacyManiaElement + public class LegacyStageForeground : CompositeDrawable { private readonly IBindable direction = new Bindable(); @@ -24,7 +25,7 @@ namespace osu.Game.Rulesets.Mania.Skinning [BackgroundDependencyLoader] private void load(ISkinSource skin, IScrollingInfo scrollingInfo) { - string bottomImage = GetManiaSkinConfig(skin, LegacyManiaSkinConfigurationLookups.BottomStageImage)?.Value + string bottomImage = skin.GetManiaSkinConfig(LegacyManiaSkinConfigurationLookups.BottomStageImage)?.Value ?? "mania-stage-bottom"; sprite = skin.GetAnimation(bottomImage, true, true)?.With(d => From ffae73a966c8afcc131c9de8b082e44950211487 Mon Sep 17 00:00:00 2001 From: mcendu Date: Sat, 13 Jun 2020 23:07:04 +0800 Subject: [PATCH 38/59] let retrievals outside mania skin components use extension https://github.com/ppy/osu/pull/9264#discussion_r439730321 --- .../Skinning/ManiaLegacySkinTransformer.cs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Skinning/ManiaLegacySkinTransformer.cs b/osu.Game.Rulesets.Mania/Skinning/ManiaLegacySkinTransformer.cs index 74a983fac8..19a107eb0d 100644 --- a/osu.Game.Rulesets.Mania/Skinning/ManiaLegacySkinTransformer.cs +++ b/osu.Game.Rulesets.Mania/Skinning/ManiaLegacySkinTransformer.cs @@ -71,8 +71,7 @@ namespace osu.Game.Rulesets.Mania.Skinning { isLegacySkin = new Lazy(() => source.GetConfig(LegacySkinConfiguration.LegacySetting.Version) != null); hasKeyTexture = new Lazy(() => source.GetAnimation( - GetConfig( - new ManiaSkinConfigurationLookup(LegacyManiaSkinConfigurationLookups.KeyImage, 0))?.Value + this.GetManiaSkinConfig(LegacyManiaSkinConfigurationLookups.KeyImage)?.Value ?? "mania-key1", true, true) != null); } @@ -128,9 +127,8 @@ namespace osu.Game.Rulesets.Mania.Skinning private Drawable getResult(HitResult result) { - string filename = GetConfig( - new ManiaSkinConfigurationLookup(hitresult_mapping[result]) - )?.Value ?? default_hitresult_skin_filenames[result]; + string filename = this.GetManiaSkinConfig(hitresult_mapping[result])?.Value + ?? default_hitresult_skin_filenames[result]; return this.GetAnimation(filename, true, true); } From 9a0a1ba0df10b87baa552e9d5869892d4cbfe3d9 Mon Sep 17 00:00:00 2001 From: mcendu Date: Sat, 13 Jun 2020 23:12:15 +0800 Subject: [PATCH 39/59] correct logic of hasKeyTexture determination --- osu.Game.Rulesets.Mania/Skinning/ManiaLegacySkinTransformer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Mania/Skinning/ManiaLegacySkinTransformer.cs b/osu.Game.Rulesets.Mania/Skinning/ManiaLegacySkinTransformer.cs index 19a107eb0d..7a2fa711e3 100644 --- a/osu.Game.Rulesets.Mania/Skinning/ManiaLegacySkinTransformer.cs +++ b/osu.Game.Rulesets.Mania/Skinning/ManiaLegacySkinTransformer.cs @@ -71,7 +71,7 @@ namespace osu.Game.Rulesets.Mania.Skinning { isLegacySkin = new Lazy(() => source.GetConfig(LegacySkinConfiguration.LegacySetting.Version) != null); hasKeyTexture = new Lazy(() => source.GetAnimation( - this.GetManiaSkinConfig(LegacyManiaSkinConfigurationLookups.KeyImage)?.Value + this.GetManiaSkinConfig(LegacyManiaSkinConfigurationLookups.KeyImage, 0)?.Value ?? "mania-key1", true, true) != null); } From eb92c3390d6b4299a2c23f0ade181ae8e4b575b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 13 Jun 2020 17:17:58 +0200 Subject: [PATCH 40/59] Check for nulls when looking for ipc.txt --- osu.Game.Tournament/IPC/FileBasedIPC.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tournament/IPC/FileBasedIPC.cs b/osu.Game.Tournament/IPC/FileBasedIPC.cs index 681839ebc4..a17491bf2d 100644 --- a/osu.Game.Tournament/IPC/FileBasedIPC.cs +++ b/osu.Game.Tournament/IPC/FileBasedIPC.cs @@ -182,7 +182,7 @@ namespace osu.Game.Tournament.IPC /// Whether an IPC directory was successfully auto-detected. public bool AutoDetectIPCLocation() => SetIPCLocation(findStablePath()); - private static bool ipcFileExistsInDirectory(string p) => File.Exists(Path.Combine(p, "ipc.txt")); + private static bool ipcFileExistsInDirectory(string p) => p != null && File.Exists(Path.Combine(p, "ipc.txt")); [CanBeNull] private string findStablePath() From 51bbd91373a54b7cfbd24151d97345e4d193cfb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 13 Jun 2020 19:28:21 +0200 Subject: [PATCH 41/59] Bring back initial directory behaviour --- osu.Game.Tournament/Screens/StablePathSelectScreen.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tournament/Screens/StablePathSelectScreen.cs b/osu.Game.Tournament/Screens/StablePathSelectScreen.cs index 958c3ef822..b4d56f60c7 100644 --- a/osu.Game.Tournament/Screens/StablePathSelectScreen.cs +++ b/osu.Game.Tournament/Screens/StablePathSelectScreen.cs @@ -36,7 +36,8 @@ namespace osu.Game.Tournament.Screens [BackgroundDependencyLoader(true)] private void load(Storage storage, OsuColour colours) { - var initialPath = new DirectoryInfo(storage.GetFullPath(string.Empty)).Parent?.FullName; + var initialStorage = (ipc as FileBasedIPC)?.IPCStorage ?? storage; + var initialPath = new DirectoryInfo(initialStorage.GetFullPath(string.Empty)).Parent?.FullName; AddRangeInternal(new Drawable[] { From add1265d5354b8ead7644b3a6389fc287fc3d7b5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 18 Jun 2020 23:35:03 +0900 Subject: [PATCH 42/59] Block screen suspend while gameplay is active --- osu.Game/Screens/Play/Player.cs | 7 ++++ .../Screens/Play/ScreenSuspensionHandler.cs | 42 +++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 osu.Game/Screens/Play/ScreenSuspensionHandler.cs diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 83991ad027..d3b88e56ae 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -125,6 +125,8 @@ namespace osu.Game.Screens.Play private GameplayBeatmap gameplayBeatmap; + private ScreenSuspensionHandler screenSuspension; + private DependencyContainer dependencies; protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) @@ -179,6 +181,7 @@ namespace osu.Game.Screens.Play InternalChild = GameplayClockContainer = new GameplayClockContainer(Beatmap.Value, Mods.Value, DrawableRuleset.GameplayStartTime); AddInternal(gameplayBeatmap = new GameplayBeatmap(playableBeatmap)); + AddInternal(screenSuspension = new ScreenSuspensionHandler(GameplayClockContainer)); dependencies.CacheAs(gameplayBeatmap); @@ -628,12 +631,16 @@ namespace osu.Game.Screens.Play public override void OnSuspending(IScreen next) { + screenSuspension?.Expire(); + fadeOut(); base.OnSuspending(next); } public override bool OnExiting(IScreen next) { + screenSuspension?.Expire(); + if (completionProgressDelegate != null && !completionProgressDelegate.Cancelled && !completionProgressDelegate.Completed) { // proceed to result screen if beatmap already finished playing diff --git a/osu.Game/Screens/Play/ScreenSuspensionHandler.cs b/osu.Game/Screens/Play/ScreenSuspensionHandler.cs new file mode 100644 index 0000000000..948276f03f --- /dev/null +++ b/osu.Game/Screens/Play/ScreenSuspensionHandler.cs @@ -0,0 +1,42 @@ +// 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.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Platform; + +namespace osu.Game.Screens.Play +{ + internal class ScreenSuspensionHandler : Component + { + private readonly GameplayClockContainer gameplayClockContainer; + private Bindable isPaused; + + [Resolved] + private GameHost host { get; set; } + + public ScreenSuspensionHandler(GameplayClockContainer gameplayClockContainer) + { + this.gameplayClockContainer = gameplayClockContainer; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + isPaused = gameplayClockContainer.IsPaused.GetBoundCopy(); + isPaused.BindValueChanged(paused => host.AllowScreenSuspension.Value = paused.NewValue, true); + } + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + + isPaused?.UnbindAll(); + + if (host != null) + host.AllowScreenSuspension.Value = true; + } + } +} From 7da56ec7fd27ebddc7253b6151b50f93ad289dd4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 18 Jun 2020 23:52:35 +0900 Subject: [PATCH 43/59] Add null check and xmldoc --- osu.Game/Screens/Play/ScreenSuspensionHandler.cs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Play/ScreenSuspensionHandler.cs b/osu.Game/Screens/Play/ScreenSuspensionHandler.cs index 948276f03f..59ad74d81a 100644 --- a/osu.Game/Screens/Play/ScreenSuspensionHandler.cs +++ b/osu.Game/Screens/Play/ScreenSuspensionHandler.cs @@ -1,6 +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 System; +using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -8,7 +10,10 @@ using osu.Framework.Platform; namespace osu.Game.Screens.Play { - internal class ScreenSuspensionHandler : Component + /// + /// Ensures screen is not suspended / dimmed while gameplay is active. + /// + public class ScreenSuspensionHandler : Component { private readonly GameplayClockContainer gameplayClockContainer; private Bindable isPaused; @@ -16,9 +21,9 @@ namespace osu.Game.Screens.Play [Resolved] private GameHost host { get; set; } - public ScreenSuspensionHandler(GameplayClockContainer gameplayClockContainer) + public ScreenSuspensionHandler([NotNull] GameplayClockContainer gameplayClockContainer) { - this.gameplayClockContainer = gameplayClockContainer; + this.gameplayClockContainer = gameplayClockContainer ?? throw new ArgumentNullException(nameof(gameplayClockContainer)); } protected override void LoadComplete() From 290ae373469bd43d66c6c965edb7e0c016ff797a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 18 Jun 2020 23:54:20 +0900 Subject: [PATCH 44/59] Add assertion of only usage game-wide --- osu.Game/Screens/Play/ScreenSuspensionHandler.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/osu.Game/Screens/Play/ScreenSuspensionHandler.cs b/osu.Game/Screens/Play/ScreenSuspensionHandler.cs index 59ad74d81a..8585a5c309 100644 --- a/osu.Game/Screens/Play/ScreenSuspensionHandler.cs +++ b/osu.Game/Screens/Play/ScreenSuspensionHandler.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Diagnostics; using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -30,6 +31,10 @@ namespace osu.Game.Screens.Play { base.LoadComplete(); + // This is the only usage game-wide of suspension changes. + // Assert to ensure we don't accidentally forget this in the future. + Debug.Assert(host.AllowScreenSuspension.Value); + isPaused = gameplayClockContainer.IsPaused.GetBoundCopy(); isPaused.BindValueChanged(paused => host.AllowScreenSuspension.Value = paused.NewValue, true); } From 22f3fd487b9cb7f346f068200b02f4fdf611e677 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 19 Jun 2020 22:43:25 +0900 Subject: [PATCH 45/59] Mark test as headless --- osu.Game.Tests/Gameplay/TestSceneGameplayClockContainer.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Tests/Gameplay/TestSceneGameplayClockContainer.cs b/osu.Game.Tests/Gameplay/TestSceneGameplayClockContainer.cs index a97566ba7b..cd3669f160 100644 --- a/osu.Game.Tests/Gameplay/TestSceneGameplayClockContainer.cs +++ b/osu.Game.Tests/Gameplay/TestSceneGameplayClockContainer.cs @@ -3,6 +3,7 @@ using System; using NUnit.Framework; +using osu.Framework.Testing; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu; using osu.Game.Screens.Play; @@ -10,6 +11,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Tests.Gameplay { + [HeadlessTest] public class TestSceneGameplayClockContainer : OsuTestScene { [Test] From 3021bdf3059fc5d9ce2165d3594828a65b5ca4fc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 20 Jun 2020 00:34:01 +0900 Subject: [PATCH 46/59] Update framework --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index b95b794004..119c309675 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -52,6 +52,6 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 6ec57e5100..bec3bc9d39 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -24,7 +24,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 0bfff24805..de5130b66a 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -70,7 +70,7 @@ - + @@ -80,7 +80,7 @@ - + From 8298a2c8a936561714233e53e2111881dff91ba4 Mon Sep 17 00:00:00 2001 From: mcendu Date: Sat, 20 Jun 2020 14:53:25 +0800 Subject: [PATCH 47/59] inline stage light lookup and clarify behavior --- osu.Game.Rulesets.Mania/Skinning/LegacyColumnBackground.cs | 2 +- osu.Game.Rulesets.Mania/Skinning/ManiaLegacySkinTransformer.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Skinning/LegacyColumnBackground.cs b/osu.Game.Rulesets.Mania/Skinning/LegacyColumnBackground.cs index 1a097405ac..b69827e2d9 100644 --- a/osu.Game.Rulesets.Mania/Skinning/LegacyColumnBackground.cs +++ b/osu.Game.Rulesets.Mania/Skinning/LegacyColumnBackground.cs @@ -32,7 +32,7 @@ namespace osu.Game.Rulesets.Mania.Skinning [BackgroundDependencyLoader] private void load(ISkinSource skin, IScrollingInfo scrollingInfo) { - string lightImage = GetManiaSkinConfig(skin, LegacyManiaSkinConfigurationLookups.LightImage, 0)?.Value + string lightImage = skin.GetManiaSkinConfig(LegacyManiaSkinConfigurationLookups.LightImage)?.Value ?? "mania-stage-light"; float leftLineWidth = GetManiaSkinConfig(skin, LegacyManiaSkinConfigurationLookups.LeftLineWidth) diff --git a/osu.Game.Rulesets.Mania/Skinning/ManiaLegacySkinTransformer.cs b/osu.Game.Rulesets.Mania/Skinning/ManiaLegacySkinTransformer.cs index 7a2fa711e3..4114bf5628 100644 --- a/osu.Game.Rulesets.Mania/Skinning/ManiaLegacySkinTransformer.cs +++ b/osu.Game.Rulesets.Mania/Skinning/ManiaLegacySkinTransformer.cs @@ -128,7 +128,7 @@ namespace osu.Game.Rulesets.Mania.Skinning private Drawable getResult(HitResult result) { string filename = this.GetManiaSkinConfig(hitresult_mapping[result])?.Value - ?? default_hitresult_skin_filenames[result]; + ?? default_hitresult_skin_filenames[result]; return this.GetAnimation(filename, true, true); } From ca555a6a5271124ff0ff55d83185ba4f6e3a034b Mon Sep 17 00:00:00 2001 From: mcendu Date: Sat, 20 Jun 2020 14:56:39 +0800 Subject: [PATCH 48/59] rename per-column skin config retrieval to GetColumnSkinConfig Removed parameter "index"; all these cases should use extension instead --- osu.Game.Rulesets.Mania/Skinning/LegacyBodyPiece.cs | 2 +- .../Skinning/LegacyColumnBackground.cs | 12 ++++++------ .../Skinning/LegacyHitExplosion.cs | 4 ++-- osu.Game.Rulesets.Mania/Skinning/LegacyKeyArea.cs | 4 ++-- .../Skinning/LegacyManiaColumnElement.cs | 4 ++-- osu.Game.Rulesets.Mania/Skinning/LegacyNotePiece.cs | 2 +- 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Skinning/LegacyBodyPiece.cs b/osu.Game.Rulesets.Mania/Skinning/LegacyBodyPiece.cs index 0c9bc97ba9..a749f80855 100644 --- a/osu.Game.Rulesets.Mania/Skinning/LegacyBodyPiece.cs +++ b/osu.Game.Rulesets.Mania/Skinning/LegacyBodyPiece.cs @@ -28,7 +28,7 @@ namespace osu.Game.Rulesets.Mania.Skinning [BackgroundDependencyLoader] private void load(ISkinSource skin, IScrollingInfo scrollingInfo, DrawableHitObject drawableObject) { - string imageName = GetManiaSkinConfig(skin, LegacyManiaSkinConfigurationLookups.HoldNoteBodyImage)?.Value + string imageName = GetColumnSkinConfig(skin, LegacyManiaSkinConfigurationLookups.HoldNoteBodyImage)?.Value ?? $"mania-note{FallbackColumnIndex}L"; sprite = skin.GetAnimation(imageName, true, true).With(d => diff --git a/osu.Game.Rulesets.Mania/Skinning/LegacyColumnBackground.cs b/osu.Game.Rulesets.Mania/Skinning/LegacyColumnBackground.cs index b69827e2d9..64a7641421 100644 --- a/osu.Game.Rulesets.Mania/Skinning/LegacyColumnBackground.cs +++ b/osu.Game.Rulesets.Mania/Skinning/LegacyColumnBackground.cs @@ -35,25 +35,25 @@ namespace osu.Game.Rulesets.Mania.Skinning string lightImage = skin.GetManiaSkinConfig(LegacyManiaSkinConfigurationLookups.LightImage)?.Value ?? "mania-stage-light"; - float leftLineWidth = GetManiaSkinConfig(skin, LegacyManiaSkinConfigurationLookups.LeftLineWidth) + float leftLineWidth = GetColumnSkinConfig(skin, LegacyManiaSkinConfigurationLookups.LeftLineWidth) ?.Value ?? 1; - float rightLineWidth = GetManiaSkinConfig(skin, LegacyManiaSkinConfigurationLookups.RightLineWidth) + float rightLineWidth = GetColumnSkinConfig(skin, LegacyManiaSkinConfigurationLookups.RightLineWidth) ?.Value ?? 1; bool hasLeftLine = leftLineWidth > 0; bool hasRightLine = rightLineWidth > 0 && skin.GetConfig(LegacySkinConfiguration.LegacySetting.Version)?.Value >= 2.4m || isLastColumn; - float lightPosition = GetManiaSkinConfig(skin, LegacyManiaSkinConfigurationLookups.LightPosition)?.Value + float lightPosition = GetColumnSkinConfig(skin, LegacyManiaSkinConfigurationLookups.LightPosition)?.Value ?? 0; - Color4 lineColour = GetManiaSkinConfig(skin, LegacyManiaSkinConfigurationLookups.ColumnLineColour)?.Value + Color4 lineColour = GetColumnSkinConfig(skin, LegacyManiaSkinConfigurationLookups.ColumnLineColour)?.Value ?? Color4.White; - Color4 backgroundColour = GetManiaSkinConfig(skin, LegacyManiaSkinConfigurationLookups.ColumnBackgroundColour)?.Value + Color4 backgroundColour = GetColumnSkinConfig(skin, LegacyManiaSkinConfigurationLookups.ColumnBackgroundColour)?.Value ?? Color4.Black; - Color4 lightColour = GetManiaSkinConfig(skin, LegacyManiaSkinConfigurationLookups.ColumnLightColour)?.Value + Color4 lightColour = GetColumnSkinConfig(skin, LegacyManiaSkinConfigurationLookups.ColumnLightColour)?.Value ?? Color4.White; InternalChildren = new Drawable[] diff --git a/osu.Game.Rulesets.Mania/Skinning/LegacyHitExplosion.cs b/osu.Game.Rulesets.Mania/Skinning/LegacyHitExplosion.cs index ce0b9fe4b6..bc93bb2615 100644 --- a/osu.Game.Rulesets.Mania/Skinning/LegacyHitExplosion.cs +++ b/osu.Game.Rulesets.Mania/Skinning/LegacyHitExplosion.cs @@ -26,10 +26,10 @@ namespace osu.Game.Rulesets.Mania.Skinning [BackgroundDependencyLoader] private void load(ISkinSource skin, IScrollingInfo scrollingInfo) { - string imageName = GetManiaSkinConfig(skin, LegacyManiaSkinConfigurationLookups.ExplosionImage)?.Value + string imageName = GetColumnSkinConfig(skin, LegacyManiaSkinConfigurationLookups.ExplosionImage)?.Value ?? "lightingN"; - float explosionScale = GetManiaSkinConfig(skin, LegacyManiaSkinConfigurationLookups.ExplosionScale)?.Value + float explosionScale = GetColumnSkinConfig(skin, LegacyManiaSkinConfigurationLookups.ExplosionScale)?.Value ?? 1; // Create a temporary animation to retrieve the number of frames, in an effort to calculate the intended frame length. diff --git a/osu.Game.Rulesets.Mania/Skinning/LegacyKeyArea.cs b/osu.Game.Rulesets.Mania/Skinning/LegacyKeyArea.cs index 7c8d1cd303..44f3e7d7b3 100644 --- a/osu.Game.Rulesets.Mania/Skinning/LegacyKeyArea.cs +++ b/osu.Game.Rulesets.Mania/Skinning/LegacyKeyArea.cs @@ -33,10 +33,10 @@ namespace osu.Game.Rulesets.Mania.Skinning [BackgroundDependencyLoader] private void load(ISkinSource skin, IScrollingInfo scrollingInfo) { - string upImage = GetManiaSkinConfig(skin, LegacyManiaSkinConfigurationLookups.KeyImage)?.Value + string upImage = GetColumnSkinConfig(skin, LegacyManiaSkinConfigurationLookups.KeyImage)?.Value ?? $"mania-key{FallbackColumnIndex}"; - string downImage = GetManiaSkinConfig(skin, LegacyManiaSkinConfigurationLookups.KeyImageDown)?.Value + string downImage = GetColumnSkinConfig(skin, LegacyManiaSkinConfigurationLookups.KeyImageDown)?.Value ?? $"mania-key{FallbackColumnIndex}D"; InternalChild = directionContainer = new Container diff --git a/osu.Game.Rulesets.Mania/Skinning/LegacyManiaColumnElement.cs b/osu.Game.Rulesets.Mania/Skinning/LegacyManiaColumnElement.cs index 0c46a00bed..3c0c632c14 100644 --- a/osu.Game.Rulesets.Mania/Skinning/LegacyManiaColumnElement.cs +++ b/osu.Game.Rulesets.Mania/Skinning/LegacyManiaColumnElement.cs @@ -42,7 +42,7 @@ namespace osu.Game.Rulesets.Mania.Skinning } } - protected IBindable GetManiaSkinConfig(ISkin skin, LegacyManiaSkinConfigurationLookups lookup, int? index = null) - => skin.GetManiaSkinConfig(lookup, index ?? Column.Index); + protected IBindable GetColumnSkinConfig(ISkin skin, LegacyManiaSkinConfigurationLookups lookup) + => skin.GetManiaSkinConfig(lookup, Column.Index); } } diff --git a/osu.Game.Rulesets.Mania/Skinning/LegacyNotePiece.cs b/osu.Game.Rulesets.Mania/Skinning/LegacyNotePiece.cs index 85523ae3c0..515c941d65 100644 --- a/osu.Game.Rulesets.Mania/Skinning/LegacyNotePiece.cs +++ b/osu.Game.Rulesets.Mania/Skinning/LegacyNotePiece.cs @@ -89,7 +89,7 @@ namespace osu.Game.Rulesets.Mania.Skinning break; } - string noteImage = GetManiaSkinConfig(skin, lookup)?.Value + string noteImage = GetColumnSkinConfig(skin, lookup)?.Value ?? $"mania-note{FallbackColumnIndex}{suffix}"; return skin.GetTexture(noteImage); From 19eb6fad7fca29af8f163ace52ba95e70383f542 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Sun, 21 Jun 2020 17:42:17 +0900 Subject: [PATCH 49/59] Make hold note ticks affect combo score rather than bonus --- osu.Game.Rulesets.Mania/Judgements/HoldNoteTickJudgement.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Judgements/HoldNoteTickJudgement.cs b/osu.Game.Rulesets.Mania/Judgements/HoldNoteTickJudgement.cs index 00b839f8ec..294aab1e4e 100644 --- a/osu.Game.Rulesets.Mania/Judgements/HoldNoteTickJudgement.cs +++ b/osu.Game.Rulesets.Mania/Judgements/HoldNoteTickJudgement.cs @@ -7,8 +7,6 @@ namespace osu.Game.Rulesets.Mania.Judgements { public class HoldNoteTickJudgement : ManiaJudgement { - public override bool AffectsCombo => false; - protected override int NumericResultFor(HitResult result) => 20; protected override double HealthIncreaseFor(HitResult result) From 44925b3951655b7a2659ac4b641da911f16461e0 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Sun, 21 Jun 2020 18:05:26 +0900 Subject: [PATCH 50/59] Reduce mania's HP drain by 20% --- osu.Game.Rulesets.Mania/ManiaRuleset.cs | 2 ++ osu.Game/Rulesets/Scoring/DrainingHealthProcessor.cs | 10 +++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index a37aaa8cc4..6ddb052585 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -44,6 +44,8 @@ namespace osu.Game.Rulesets.Mania public override ScoreProcessor CreateScoreProcessor() => new ManiaScoreProcessor(); + public override HealthProcessor CreateHealthProcessor(double drainStartTime) => new DrainingHealthProcessor(drainStartTime, 0.2); + public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new ManiaBeatmapConverter(beatmap, this); public override PerformanceCalculator CreatePerformanceCalculator(WorkingBeatmap beatmap, ScoreInfo score) => new ManiaPerformanceCalculator(this, beatmap, score); diff --git a/osu.Game/Rulesets/Scoring/DrainingHealthProcessor.cs b/osu.Game/Rulesets/Scoring/DrainingHealthProcessor.cs index 982f527517..2d3754841b 100644 --- a/osu.Game/Rulesets/Scoring/DrainingHealthProcessor.cs +++ b/osu.Game/Rulesets/Scoring/DrainingHealthProcessor.cs @@ -44,6 +44,7 @@ namespace osu.Game.Rulesets.Scoring private double gameplayEndTime; private readonly double drainStartTime; + private readonly double drainLenience; private readonly List<(double time, double health)> healthIncreases = new List<(double, double)>(); private double targetMinimumHealth; @@ -55,9 +56,14 @@ namespace osu.Game.Rulesets.Scoring /// Creates a new . /// /// The time after which draining should begin. - public DrainingHealthProcessor(double drainStartTime) + /// A lenience to apply to the default drain rate.
+ /// A value of 0 uses the default drain rate.
+ /// A value of 0.5 halves the drain rate.
+ /// A value of 1 completely removes drain. + public DrainingHealthProcessor(double drainStartTime, double drainLenience = 0) { this.drainStartTime = drainStartTime; + this.drainLenience = drainLenience; } protected override void Update() @@ -95,6 +101,8 @@ namespace osu.Game.Rulesets.Scoring ))); targetMinimumHealth = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.DrainRate, min_health_target, mid_health_target, max_health_target); + targetMinimumHealth += drainLenience * (1 - targetMinimumHealth); + targetMinimumHealth = Math.Min(1, targetMinimumHealth); base.ApplyBeatmap(beatmap); } From 9fbe2fa80a140eef3a8babf39c02bd003db56bb9 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Sun, 21 Jun 2020 19:31:00 +0900 Subject: [PATCH 51/59] Add comments, change to clamp --- osu.Game/Rulesets/Scoring/DrainingHealthProcessor.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Scoring/DrainingHealthProcessor.cs b/osu.Game/Rulesets/Scoring/DrainingHealthProcessor.cs index 2d3754841b..ef341575fa 100644 --- a/osu.Game/Rulesets/Scoring/DrainingHealthProcessor.cs +++ b/osu.Game/Rulesets/Scoring/DrainingHealthProcessor.cs @@ -101,8 +101,12 @@ namespace osu.Game.Rulesets.Scoring ))); targetMinimumHealth = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.DrainRate, min_health_target, mid_health_target, max_health_target); + + // Add back a portion of the amount of HP to be drained, depending on the lenience requested. targetMinimumHealth += drainLenience * (1 - targetMinimumHealth); - targetMinimumHealth = Math.Min(1, targetMinimumHealth); + + // Ensure the target HP is within an acceptable range. + targetMinimumHealth = Math.Clamp(targetMinimumHealth, 0, 1); base.ApplyBeatmap(beatmap); } From 599543acb6cf7fa44ff518d7f43eba47ec2e53b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 21 Jun 2020 18:02:09 +0200 Subject: [PATCH 52/59] Extract abstract hitobject sample test class --- .../Gameplay/HitObjectSampleTest.cs | 183 ++++++++++++++ .../Gameplay/TestSceneHitObjectSamples.cs | 239 +++--------------- 2 files changed, 216 insertions(+), 206 deletions(-) create mode 100644 osu.Game.Tests/Gameplay/HitObjectSampleTest.cs diff --git a/osu.Game.Tests/Gameplay/HitObjectSampleTest.cs b/osu.Game.Tests/Gameplay/HitObjectSampleTest.cs new file mode 100644 index 0000000000..6621344b6e --- /dev/null +++ b/osu.Game.Tests/Gameplay/HitObjectSampleTest.cs @@ -0,0 +1,183 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using osu.Framework.Allocation; +using osu.Framework.Audio; +using osu.Framework.IO.Stores; +using osu.Framework.Timing; +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.Formats; +using osu.Game.IO; +using osu.Game.Rulesets; +using osu.Game.Skinning; +using osu.Game.Storyboards; +using osu.Game.Tests.Resources; +using osu.Game.Tests.Visual; +using osu.Game.Users; + +namespace osu.Game.Tests.Gameplay +{ + public abstract class HitObjectSampleTest : PlayerTestScene + { + private readonly SkinInfo userSkinInfo = new SkinInfo(); + + private readonly BeatmapInfo beatmapInfo = new BeatmapInfo + { + BeatmapSet = new BeatmapSetInfo(), + Metadata = new BeatmapMetadata + { + Author = User.SYSTEM_USER + } + }; + + private readonly TestResourceStore userSkinResourceStore = new TestResourceStore(); + private readonly TestResourceStore beatmapSkinResourceStore = new TestResourceStore(); + private SkinSourceDependencyContainer dependencies; + private IBeatmap currentTestBeatmap; + protected override bool HasCustomSteps => true; + + protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) + => new DependencyContainer(dependencies = new SkinSourceDependencyContainer(base.CreateChildDependencies(parent))); + + protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) => currentTestBeatmap; + + protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap, Storyboard storyboard = null) + => new TestWorkingBeatmap(beatmapInfo, beatmapSkinResourceStore, beatmap, storyboard, Clock, Audio); + + protected void CreateTestWithBeatmap(string filename) + { + CreateTest(() => + { + AddStep("clear performed lookups", () => + { + userSkinResourceStore.PerformedLookups.Clear(); + beatmapSkinResourceStore.PerformedLookups.Clear(); + }); + + AddStep($"load {filename}", () => + { + using (var reader = new LineBufferedReader(TestResources.OpenResource($"SampleLookups/{filename}"))) + currentTestBeatmap = Decoder.GetDecoder(reader).Decode(reader); + }); + }); + } + + protected void SetupSkins(string beatmapFile, string userFile) + { + AddStep("setup skins", () => + { + userSkinInfo.Files = new List + { + new SkinFileInfo + { + Filename = userFile, + FileInfo = new IO.FileInfo { Hash = userFile } + } + }; + + beatmapInfo.BeatmapSet.Files = new List + { + new BeatmapSetFileInfo + { + Filename = beatmapFile, + FileInfo = new IO.FileInfo { Hash = beatmapFile } + } + }; + + // Need to refresh the cached skin source to refresh the skin resource store. + dependencies.SkinSource = new SkinProvidingContainer(new LegacySkin(userSkinInfo, userSkinResourceStore, Audio)); + }); + } + + protected void AssertBeatmapLookup(string name) => AddAssert($"\"{name}\" looked up from beatmap skin", + () => !userSkinResourceStore.PerformedLookups.Contains(name) && beatmapSkinResourceStore.PerformedLookups.Contains(name)); + + protected void AssertUserLookup(string name) => AddAssert($"\"{name}\" looked up from user skin", + () => !beatmapSkinResourceStore.PerformedLookups.Contains(name) && userSkinResourceStore.PerformedLookups.Contains(name)); + + protected class SkinSourceDependencyContainer : IReadOnlyDependencyContainer + { + public ISkinSource SkinSource; + + private readonly IReadOnlyDependencyContainer fallback; + + public SkinSourceDependencyContainer(IReadOnlyDependencyContainer fallback) + { + this.fallback = fallback; + } + + public object Get(Type type) + { + if (type == typeof(ISkinSource)) + return SkinSource; + + return fallback.Get(type); + } + + public object Get(Type type, CacheInfo info) + { + if (type == typeof(ISkinSource)) + return SkinSource; + + return fallback.Get(type, info); + } + + public void Inject(T instance) where T : class + { + // Never used directly + } + } + + protected class TestResourceStore : IResourceStore + { + public readonly List PerformedLookups = new List(); + + public byte[] Get(string name) + { + markLookup(name); + return Array.Empty(); + } + + public Task GetAsync(string name) + { + markLookup(name); + return Task.FromResult(Array.Empty()); + } + + public Stream GetStream(string name) + { + markLookup(name); + return new MemoryStream(); + } + + private void markLookup(string name) => PerformedLookups.Add(name.Substring(name.LastIndexOf(Path.DirectorySeparatorChar) + 1)); + + public IEnumerable GetAvailableResources() => Enumerable.Empty(); + + public void Dispose() + { + } + } + + private class TestWorkingBeatmap : ClockBackedTestWorkingBeatmap + { + private readonly BeatmapInfo skinBeatmapInfo; + private readonly IResourceStore resourceStore; + + public TestWorkingBeatmap(BeatmapInfo skinBeatmapInfo, IResourceStore resourceStore, IBeatmap beatmap, Storyboard storyboard, IFrameBasedClock referenceClock, AudioManager audio, + double length = 60000) + : base(beatmap, storyboard, referenceClock, audio, length) + { + this.skinBeatmapInfo = skinBeatmapInfo; + this.resourceStore = resourceStore; + } + + protected override ISkin GetSkin() => new LegacyBeatmapSkin(skinBeatmapInfo, resourceStore, AudioManager); + } + } +} diff --git a/osu.Game.Tests/Gameplay/TestSceneHitObjectSamples.cs b/osu.Game.Tests/Gameplay/TestSceneHitObjectSamples.cs index acefaa006a..6144179d31 100644 --- a/osu.Game.Tests/Gameplay/TestSceneHitObjectSamples.cs +++ b/osu.Game.Tests/Gameplay/TestSceneHitObjectSamples.cs @@ -1,52 +1,17 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading.Tasks; using NUnit.Framework; -using osu.Framework.Allocation; -using osu.Framework.Audio; -using osu.Framework.IO.Stores; using osu.Framework.Testing; -using osu.Framework.Timing; -using osu.Game.Beatmaps; -using osu.Game.Beatmaps.Formats; -using osu.Game.IO; using osu.Game.Rulesets; -using osu.Game.Skinning; -using osu.Game.Storyboards; -using osu.Game.Tests.Resources; -using osu.Game.Tests.Visual.Gameplay; -using osu.Game.Users; +using osu.Game.Rulesets.Osu; namespace osu.Game.Tests.Gameplay { [HeadlessTest] - public class TestSceneHitObjectSamples : OsuPlayerTestScene + public class TestSceneHitObjectSamples : HitObjectSampleTest { - private readonly SkinInfo userSkinInfo = new SkinInfo(); - - private readonly BeatmapInfo beatmapInfo = new BeatmapInfo - { - BeatmapSet = new BeatmapSetInfo(), - Metadata = new BeatmapMetadata - { - Author = User.SYSTEM_USER - } - }; - - private readonly TestResourceStore userSkinResourceStore = new TestResourceStore(); - private readonly TestResourceStore beatmapSkinResourceStore = new TestResourceStore(); - - protected override bool HasCustomSteps => true; - - private SkinSourceDependencyContainer dependencies; - - protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) - => new DependencyContainer(dependencies = new SkinSourceDependencyContainer(base.CreateChildDependencies(parent))); + protected override Ruleset CreatePlayerRuleset() => new OsuRuleset(); /// /// Tests that a hitobject which provides no custom sample set retrieves samples from the user skin. @@ -56,11 +21,11 @@ namespace osu.Game.Tests.Gameplay { const string expected_sample = "normal-hitnormal"; - setupSkins(expected_sample, expected_sample); + SetupSkins(expected_sample, expected_sample); - createTestWithBeatmap("hitobject-skin-sample.osu"); + CreateTestWithBeatmap("hitobject-skin-sample.osu"); - assertUserLookup(expected_sample); + AssertUserLookup(expected_sample); } /// @@ -71,11 +36,11 @@ namespace osu.Game.Tests.Gameplay { const string expected_sample = "normal-hitnormal"; - setupSkins(expected_sample, expected_sample); + SetupSkins(expected_sample, expected_sample); - createTestWithBeatmap("hitobject-beatmap-sample.osu"); + CreateTestWithBeatmap("hitobject-beatmap-sample.osu"); - assertBeatmapLookup(expected_sample); + AssertBeatmapLookup(expected_sample); } /// @@ -86,11 +51,11 @@ namespace osu.Game.Tests.Gameplay { const string expected_sample = "normal-hitnormal"; - setupSkins(null, expected_sample); + SetupSkins(null, expected_sample); - createTestWithBeatmap("hitobject-beatmap-sample.osu"); + CreateTestWithBeatmap("hitobject-beatmap-sample.osu"); - assertUserLookup(expected_sample); + AssertUserLookup(expected_sample); } /// @@ -102,11 +67,11 @@ namespace osu.Game.Tests.Gameplay [TestCase("normal-hitnormal")] public void TestDefaultCustomSampleFromBeatmap(string expectedSample) { - setupSkins(expectedSample, expectedSample); + SetupSkins(expectedSample, expectedSample); - createTestWithBeatmap("hitobject-beatmap-custom-sample.osu"); + CreateTestWithBeatmap("hitobject-beatmap-custom-sample.osu"); - assertBeatmapLookup(expectedSample); + AssertBeatmapLookup(expectedSample); } /// @@ -118,11 +83,11 @@ namespace osu.Game.Tests.Gameplay [TestCase("normal-hitnormal")] public void TestDefaultCustomSampleFromUserSkinFallback(string expectedSample) { - setupSkins(string.Empty, expectedSample); + SetupSkins(string.Empty, expectedSample); - createTestWithBeatmap("hitobject-beatmap-custom-sample.osu"); + CreateTestWithBeatmap("hitobject-beatmap-custom-sample.osu"); - assertUserLookup(expectedSample); + AssertUserLookup(expectedSample); } /// @@ -133,11 +98,11 @@ namespace osu.Game.Tests.Gameplay { const string expected_sample = "hit_1.wav"; - setupSkins(expected_sample, expected_sample); + SetupSkins(expected_sample, expected_sample); - createTestWithBeatmap("file-beatmap-sample.osu"); + CreateTestWithBeatmap("file-beatmap-sample.osu"); - assertBeatmapLookup(expected_sample); + AssertBeatmapLookup(expected_sample); } /// @@ -148,11 +113,11 @@ namespace osu.Game.Tests.Gameplay { const string expected_sample = "normal-hitnormal"; - setupSkins(expected_sample, expected_sample); + SetupSkins(expected_sample, expected_sample); - createTestWithBeatmap("controlpoint-skin-sample.osu"); + CreateTestWithBeatmap("controlpoint-skin-sample.osu"); - assertUserLookup(expected_sample); + AssertUserLookup(expected_sample); } /// @@ -163,11 +128,11 @@ namespace osu.Game.Tests.Gameplay { const string expected_sample = "normal-hitnormal"; - setupSkins(expected_sample, expected_sample); + SetupSkins(expected_sample, expected_sample); - createTestWithBeatmap("controlpoint-beatmap-sample.osu"); + CreateTestWithBeatmap("controlpoint-beatmap-sample.osu"); - assertBeatmapLookup(expected_sample); + AssertBeatmapLookup(expected_sample); } /// @@ -177,11 +142,11 @@ namespace osu.Game.Tests.Gameplay [TestCase("normal-hitnormal")] public void TestControlPointCustomSampleFromBeatmap(string sampleName) { - setupSkins(sampleName, sampleName); + SetupSkins(sampleName, sampleName); - createTestWithBeatmap("controlpoint-beatmap-custom-sample.osu"); + CreateTestWithBeatmap("controlpoint-beatmap-custom-sample.osu"); - assertBeatmapLookup(sampleName); + AssertBeatmapLookup(sampleName); } /// @@ -192,149 +157,11 @@ namespace osu.Game.Tests.Gameplay { const string expected_sample = "normal-hitnormal3"; - setupSkins(expected_sample, expected_sample); + SetupSkins(expected_sample, expected_sample); - createTestWithBeatmap("hitobject-beatmap-custom-sample-override.osu"); + CreateTestWithBeatmap("hitobject-beatmap-custom-sample-override.osu"); - assertBeatmapLookup(expected_sample); - } - - protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) => currentTestBeatmap; - - protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap, Storyboard storyboard = null) - => new TestWorkingBeatmap(beatmapInfo, beatmapSkinResourceStore, beatmap, storyboard, Clock, Audio); - - private IBeatmap currentTestBeatmap; - - private void createTestWithBeatmap(string filename) - { - CreateTest(() => - { - AddStep("clear performed lookups", () => - { - userSkinResourceStore.PerformedLookups.Clear(); - beatmapSkinResourceStore.PerformedLookups.Clear(); - }); - - AddStep($"load {filename}", () => - { - using (var reader = new LineBufferedReader(TestResources.OpenResource($"SampleLookups/{filename}"))) - currentTestBeatmap = Decoder.GetDecoder(reader).Decode(reader); - }); - }); - } - - private void setupSkins(string beatmapFile, string userFile) - { - AddStep("setup skins", () => - { - userSkinInfo.Files = new List - { - new SkinFileInfo - { - Filename = userFile, - FileInfo = new IO.FileInfo { Hash = userFile } - } - }; - - beatmapInfo.BeatmapSet.Files = new List - { - new BeatmapSetFileInfo - { - Filename = beatmapFile, - FileInfo = new IO.FileInfo { Hash = beatmapFile } - } - }; - - // Need to refresh the cached skin source to refresh the skin resource store. - dependencies.SkinSource = new SkinProvidingContainer(new LegacySkin(userSkinInfo, userSkinResourceStore, Audio)); - }); - } - - private void assertBeatmapLookup(string name) => AddAssert($"\"{name}\" looked up from beatmap skin", - () => !userSkinResourceStore.PerformedLookups.Contains(name) && beatmapSkinResourceStore.PerformedLookups.Contains(name)); - - private void assertUserLookup(string name) => AddAssert($"\"{name}\" looked up from user skin", - () => !beatmapSkinResourceStore.PerformedLookups.Contains(name) && userSkinResourceStore.PerformedLookups.Contains(name)); - - private class SkinSourceDependencyContainer : IReadOnlyDependencyContainer - { - public ISkinSource SkinSource; - - private readonly IReadOnlyDependencyContainer fallback; - - public SkinSourceDependencyContainer(IReadOnlyDependencyContainer fallback) - { - this.fallback = fallback; - } - - public object Get(Type type) - { - if (type == typeof(ISkinSource)) - return SkinSource; - - return fallback.Get(type); - } - - public object Get(Type type, CacheInfo info) - { - if (type == typeof(ISkinSource)) - return SkinSource; - - return fallback.Get(type, info); - } - - public void Inject(T instance) where T : class - { - // Never used directly - } - } - - private class TestResourceStore : IResourceStore - { - public readonly List PerformedLookups = new List(); - - public byte[] Get(string name) - { - markLookup(name); - return Array.Empty(); - } - - public Task GetAsync(string name) - { - markLookup(name); - return Task.FromResult(Array.Empty()); - } - - public Stream GetStream(string name) - { - markLookup(name); - return new MemoryStream(); - } - - private void markLookup(string name) => PerformedLookups.Add(name.Substring(name.LastIndexOf(Path.DirectorySeparatorChar) + 1)); - - public IEnumerable GetAvailableResources() => Enumerable.Empty(); - - public void Dispose() - { - } - } - - private class TestWorkingBeatmap : ClockBackedTestWorkingBeatmap - { - private readonly BeatmapInfo skinBeatmapInfo; - private readonly IResourceStore resourceStore; - - public TestWorkingBeatmap(BeatmapInfo skinBeatmapInfo, IResourceStore resourceStore, IBeatmap beatmap, Storyboard storyboard, IFrameBasedClock referenceClock, AudioManager audio, - double length = 60000) - : base(beatmap, storyboard, referenceClock, audio, length) - { - this.skinBeatmapInfo = skinBeatmapInfo; - this.resourceStore = resourceStore; - } - - protected override ISkin GetSkin() => new LegacyBeatmapSkin(skinBeatmapInfo, resourceStore, AudioManager); + AssertBeatmapLookup(expected_sample); } } } From 4a8a673d41a276a540cab16806bd80beb29308e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 21 Jun 2020 18:19:33 +0200 Subject: [PATCH 53/59] Decouple abstract sample test from TestResources --- osu.Game.Tests/Gameplay/HitObjectSampleTest.cs | 5 +++-- osu.Game.Tests/Gameplay/TestSceneHitObjectSamples.cs | 3 +++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Gameplay/HitObjectSampleTest.cs b/osu.Game.Tests/Gameplay/HitObjectSampleTest.cs index 6621344b6e..9c43690a95 100644 --- a/osu.Game.Tests/Gameplay/HitObjectSampleTest.cs +++ b/osu.Game.Tests/Gameplay/HitObjectSampleTest.cs @@ -16,7 +16,6 @@ using osu.Game.IO; using osu.Game.Rulesets; using osu.Game.Skinning; using osu.Game.Storyboards; -using osu.Game.Tests.Resources; using osu.Game.Tests.Visual; using osu.Game.Users; @@ -24,6 +23,8 @@ namespace osu.Game.Tests.Gameplay { public abstract class HitObjectSampleTest : PlayerTestScene { + protected abstract IResourceStore Resources { get; } + private readonly SkinInfo userSkinInfo = new SkinInfo(); private readonly BeatmapInfo beatmapInfo = new BeatmapInfo @@ -61,7 +62,7 @@ namespace osu.Game.Tests.Gameplay AddStep($"load {filename}", () => { - using (var reader = new LineBufferedReader(TestResources.OpenResource($"SampleLookups/{filename}"))) + using (var reader = new LineBufferedReader(Resources.GetStream($"Resources/SampleLookups/{filename}"))) currentTestBeatmap = Decoder.GetDecoder(reader).Decode(reader); }); }); diff --git a/osu.Game.Tests/Gameplay/TestSceneHitObjectSamples.cs b/osu.Game.Tests/Gameplay/TestSceneHitObjectSamples.cs index 6144179d31..78bdfeb80e 100644 --- a/osu.Game.Tests/Gameplay/TestSceneHitObjectSamples.cs +++ b/osu.Game.Tests/Gameplay/TestSceneHitObjectSamples.cs @@ -2,9 +2,11 @@ // See the LICENCE file in the repository root for full licence text. using NUnit.Framework; +using osu.Framework.IO.Stores; using osu.Framework.Testing; using osu.Game.Rulesets; using osu.Game.Rulesets.Osu; +using osu.Game.Tests.Resources; namespace osu.Game.Tests.Gameplay { @@ -12,6 +14,7 @@ namespace osu.Game.Tests.Gameplay public class TestSceneHitObjectSamples : HitObjectSampleTest { protected override Ruleset CreatePlayerRuleset() => new OsuRuleset(); + protected override IResourceStore Resources => TestResources.GetStore(); /// /// Tests that a hitobject which provides no custom sample set retrieves samples from the user skin. From 4bba0c7359c857bc19d794c5b7b269e001d4d45e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 21 Jun 2020 18:20:36 +0200 Subject: [PATCH 54/59] Move abstract sample test to main game project --- osu.Game.Tests/Gameplay/TestSceneHitObjectSamples.cs | 1 + .../Gameplay => osu.Game/Tests/Beatmaps}/HitObjectSampleTest.cs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) rename {osu.Game.Tests/Gameplay => osu.Game/Tests/Beatmaps}/HitObjectSampleTest.cs (99%) diff --git a/osu.Game.Tests/Gameplay/TestSceneHitObjectSamples.cs b/osu.Game.Tests/Gameplay/TestSceneHitObjectSamples.cs index 78bdfeb80e..ef6efb7fec 100644 --- a/osu.Game.Tests/Gameplay/TestSceneHitObjectSamples.cs +++ b/osu.Game.Tests/Gameplay/TestSceneHitObjectSamples.cs @@ -6,6 +6,7 @@ using osu.Framework.IO.Stores; using osu.Framework.Testing; using osu.Game.Rulesets; using osu.Game.Rulesets.Osu; +using osu.Game.Tests.Beatmaps; using osu.Game.Tests.Resources; namespace osu.Game.Tests.Gameplay diff --git a/osu.Game.Tests/Gameplay/HitObjectSampleTest.cs b/osu.Game/Tests/Beatmaps/HitObjectSampleTest.cs similarity index 99% rename from osu.Game.Tests/Gameplay/HitObjectSampleTest.cs rename to osu.Game/Tests/Beatmaps/HitObjectSampleTest.cs index 9c43690a95..91fca2c1bf 100644 --- a/osu.Game.Tests/Gameplay/HitObjectSampleTest.cs +++ b/osu.Game/Tests/Beatmaps/HitObjectSampleTest.cs @@ -19,7 +19,7 @@ using osu.Game.Storyboards; using osu.Game.Tests.Visual; using osu.Game.Users; -namespace osu.Game.Tests.Gameplay +namespace osu.Game.Tests.Beatmaps { public abstract class HitObjectSampleTest : PlayerTestScene { From 07cbc3e68343b83b17b4e43f8302f84833417f99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 21 Jun 2020 23:04:59 +0200 Subject: [PATCH 55/59] Privatise and seal whatever possible --- osu.Game/Tests/Beatmaps/HitObjectSampleTest.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game/Tests/Beatmaps/HitObjectSampleTest.cs b/osu.Game/Tests/Beatmaps/HitObjectSampleTest.cs index 91fca2c1bf..b4ce322165 100644 --- a/osu.Game/Tests/Beatmaps/HitObjectSampleTest.cs +++ b/osu.Game/Tests/Beatmaps/HitObjectSampleTest.cs @@ -40,14 +40,14 @@ namespace osu.Game.Tests.Beatmaps private readonly TestResourceStore beatmapSkinResourceStore = new TestResourceStore(); private SkinSourceDependencyContainer dependencies; private IBeatmap currentTestBeatmap; - protected override bool HasCustomSteps => true; + protected sealed override bool HasCustomSteps => true; - protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) + protected sealed override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) => new DependencyContainer(dependencies = new SkinSourceDependencyContainer(base.CreateChildDependencies(parent))); - protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) => currentTestBeatmap; + protected sealed override IBeatmap CreateBeatmap(RulesetInfo ruleset) => currentTestBeatmap; - protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap, Storyboard storyboard = null) + protected sealed override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap, Storyboard storyboard = null) => new TestWorkingBeatmap(beatmapInfo, beatmapSkinResourceStore, beatmap, storyboard, Clock, Audio); protected void CreateTestWithBeatmap(string filename) @@ -101,7 +101,7 @@ namespace osu.Game.Tests.Beatmaps protected void AssertUserLookup(string name) => AddAssert($"\"{name}\" looked up from user skin", () => !beatmapSkinResourceStore.PerformedLookups.Contains(name) && userSkinResourceStore.PerformedLookups.Contains(name)); - protected class SkinSourceDependencyContainer : IReadOnlyDependencyContainer + private class SkinSourceDependencyContainer : IReadOnlyDependencyContainer { public ISkinSource SkinSource; @@ -134,7 +134,7 @@ namespace osu.Game.Tests.Beatmaps } } - protected class TestResourceStore : IResourceStore + private class TestResourceStore : IResourceStore { public readonly List PerformedLookups = new List(); From ad85c5f538a162ca9973301331db8baa8110b17d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 21 Jun 2020 22:04:10 +0200 Subject: [PATCH 56/59] Add base legacy skin transformer --- .../Skinning/CatchLegacySkinTransformer.cs | 23 ++++------- .../Skinning/ManiaLegacySkinTransformer.cs | 26 +++++-------- .../Skinning/OsuLegacySkinTransformer.cs | 38 +++++++------------ .../Skinning/TaikoLegacySkinTransformer.cs | 17 +++------ osu.Game/Skinning/LegacySkinTransformer.cs | 35 +++++++++++++++++ 5 files changed, 71 insertions(+), 68 deletions(-) create mode 100644 osu.Game/Skinning/LegacySkinTransformer.cs diff --git a/osu.Game.Rulesets.Catch/Skinning/CatchLegacySkinTransformer.cs b/osu.Game.Rulesets.Catch/Skinning/CatchLegacySkinTransformer.cs index 954f2dfc5f..d929da1a29 100644 --- a/osu.Game.Rulesets.Catch/Skinning/CatchLegacySkinTransformer.cs +++ b/osu.Game.Rulesets.Catch/Skinning/CatchLegacySkinTransformer.cs @@ -2,26 +2,21 @@ // See the LICENCE file in the repository root for full licence text. using Humanizer; -using osu.Framework.Audio.Sample; using osu.Framework.Bindables; using osu.Framework.Graphics; -using osu.Framework.Graphics.Textures; -using osu.Game.Audio; using osu.Game.Skinning; using osuTK; namespace osu.Game.Rulesets.Catch.Skinning { - public class CatchLegacySkinTransformer : ISkin + public class CatchLegacySkinTransformer : LegacySkinTransformer { - private readonly ISkin source; - - public CatchLegacySkinTransformer(ISkin source) + public CatchLegacySkinTransformer(ISkinSource source) + : base(source) { - this.source = source; } - public Drawable GetDrawableComponent(ISkinComponent component) + public override Drawable GetDrawableComponent(ISkinComponent component) { if (!(component is CatchSkinComponent catchSkinComponent)) return null; @@ -61,19 +56,15 @@ namespace osu.Game.Rulesets.Catch.Skinning return null; } - public Texture GetTexture(string componentName) => source.GetTexture(componentName); - - public SampleChannel GetSample(ISampleInfo sample) => source.GetSample(sample); - - public IBindable GetConfig(TLookup lookup) + public override IBindable GetConfig(TLookup lookup) { switch (lookup) { case CatchSkinColour colour: - return source.GetConfig(new SkinCustomColourLookup(colour)); + return Source.GetConfig(new SkinCustomColourLookup(colour)); } - return source.GetConfig(lookup); + return Source.GetConfig(lookup); } } } diff --git a/osu.Game.Rulesets.Mania/Skinning/ManiaLegacySkinTransformer.cs b/osu.Game.Rulesets.Mania/Skinning/ManiaLegacySkinTransformer.cs index 4114bf5628..84e88a10be 100644 --- a/osu.Game.Rulesets.Mania/Skinning/ManiaLegacySkinTransformer.cs +++ b/osu.Game.Rulesets.Mania/Skinning/ManiaLegacySkinTransformer.cs @@ -3,11 +3,8 @@ using System; using osu.Framework.Graphics; -using osu.Framework.Graphics.Textures; -using osu.Framework.Audio.Sample; using osu.Framework.Bindables; using osu.Game.Rulesets.Scoring; -using osu.Game.Audio; using osu.Game.Beatmaps; using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Skinning; @@ -15,9 +12,8 @@ using System.Collections.Generic; namespace osu.Game.Rulesets.Mania.Skinning { - public class ManiaLegacySkinTransformer : ISkin + public class ManiaLegacySkinTransformer : LegacySkinTransformer { - private readonly ISkin source; private readonly ManiaBeatmap beatmap; /// @@ -59,23 +55,23 @@ namespace osu.Game.Rulesets.Mania.Skinning private Lazy hasKeyTexture; public ManiaLegacySkinTransformer(ISkinSource source, IBeatmap beatmap) + : base(source) { - this.source = source; this.beatmap = (ManiaBeatmap)beatmap; - source.SourceChanged += sourceChanged; + Source.SourceChanged += sourceChanged; sourceChanged(); } private void sourceChanged() { - isLegacySkin = new Lazy(() => source.GetConfig(LegacySkinConfiguration.LegacySetting.Version) != null); - hasKeyTexture = new Lazy(() => source.GetAnimation( + isLegacySkin = new Lazy(() => Source.GetConfig(LegacySkinConfiguration.LegacySetting.Version) != null); + hasKeyTexture = new Lazy(() => Source.GetAnimation( this.GetManiaSkinConfig(LegacyManiaSkinConfigurationLookups.KeyImage, 0)?.Value ?? "mania-key1", true, true) != null); } - public Drawable GetDrawableComponent(ISkinComponent component) + public override Drawable GetDrawableComponent(ISkinComponent component) { switch (component) { @@ -133,16 +129,12 @@ namespace osu.Game.Rulesets.Mania.Skinning return this.GetAnimation(filename, true, true); } - public Texture GetTexture(string componentName) => source.GetTexture(componentName); - - public SampleChannel GetSample(ISampleInfo sample) => source.GetSample(sample); - - public IBindable GetConfig(TLookup lookup) + public override IBindable GetConfig(TLookup lookup) { if (lookup is ManiaSkinConfigurationLookup maniaLookup) - return source.GetConfig(new LegacyManiaSkinConfigurationLookup(beatmap.TotalColumns, maniaLookup.Lookup, maniaLookup.TargetColumn)); + return Source.GetConfig(new LegacyManiaSkinConfigurationLookup(beatmap.TotalColumns, maniaLookup.Lookup, maniaLookup.TargetColumn)); - return source.GetConfig(lookup); + return Source.GetConfig(lookup); } } } diff --git a/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs b/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs index ba0003b5cd..3e5758ca01 100644 --- a/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs +++ b/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs @@ -2,20 +2,15 @@ // See the LICENCE file in the repository root for full licence text. using System; -using osu.Framework.Audio.Sample; using osu.Framework.Bindables; using osu.Framework.Graphics; -using osu.Framework.Graphics.Textures; -using osu.Game.Audio; using osu.Game.Skinning; using osuTK; namespace osu.Game.Rulesets.Osu.Skinning { - public class OsuLegacySkinTransformer : ISkin + public class OsuLegacySkinTransformer : LegacySkinTransformer { - private readonly ISkin source; - private Lazy hasHitCircle; /// @@ -26,19 +21,18 @@ namespace osu.Game.Rulesets.Osu.Skinning public const float LEGACY_CIRCLE_RADIUS = 64 - 5; public OsuLegacySkinTransformer(ISkinSource source) + : base(source) { - this.source = source; - - source.SourceChanged += sourceChanged; + Source.SourceChanged += sourceChanged; sourceChanged(); } private void sourceChanged() { - hasHitCircle = new Lazy(() => source.GetTexture("hitcircle") != null); + hasHitCircle = new Lazy(() => Source.GetTexture("hitcircle") != null); } - public Drawable GetDrawableComponent(ISkinComponent component) + public override Drawable GetDrawableComponent(ISkinComponent component) { if (!(component is OsuSkinComponent osuComponent)) return null; @@ -85,13 +79,13 @@ namespace osu.Game.Rulesets.Osu.Skinning return null; case OsuSkinComponents.Cursor: - if (source.GetTexture("cursor") != null) + if (Source.GetTexture("cursor") != null) return new LegacyCursor(); return null; case OsuSkinComponents.CursorTrail: - if (source.GetTexture("cursortrail") != null) + if (Source.GetTexture("cursortrail") != null) return new LegacyCursorTrail(); return null; @@ -102,7 +96,7 @@ namespace osu.Game.Rulesets.Osu.Skinning return !hasFont(font) ? null - : new LegacySpriteText(source, font) + : new LegacySpriteText(Source, font) { // stable applies a blanket 0.8x scale to hitcircle fonts Scale = new Vector2(0.8f), @@ -113,16 +107,12 @@ namespace osu.Game.Rulesets.Osu.Skinning return null; } - public Texture GetTexture(string componentName) => source.GetTexture(componentName); - - public SampleChannel GetSample(ISampleInfo sample) => source.GetSample(sample); - - public IBindable GetConfig(TLookup lookup) + public override IBindable GetConfig(TLookup lookup) { switch (lookup) { case OsuSkinColour colour: - return source.GetConfig(new SkinCustomColourLookup(colour)); + return Source.GetConfig(new SkinCustomColourLookup(colour)); case OsuSkinConfiguration osuLookup: switch (osuLookup) @@ -136,16 +126,16 @@ namespace osu.Game.Rulesets.Osu.Skinning case OsuSkinConfiguration.HitCircleOverlayAboveNumber: // See https://osu.ppy.sh/help/wiki/Skinning/skin.ini#%5Bgeneral%5D // HitCircleOverlayAboveNumer (with typo) should still be supported for now. - return source.GetConfig(OsuSkinConfiguration.HitCircleOverlayAboveNumber) ?? - source.GetConfig(OsuSkinConfiguration.HitCircleOverlayAboveNumer); + return Source.GetConfig(OsuSkinConfiguration.HitCircleOverlayAboveNumber) ?? + Source.GetConfig(OsuSkinConfiguration.HitCircleOverlayAboveNumer); } break; } - return source.GetConfig(lookup); + return Source.GetConfig(lookup); } - private bool hasFont(string fontName) => source.GetTexture($"{fontName}-0") != null; + private bool hasFont(string fontName) => Source.GetTexture($"{fontName}-0") != null; } } diff --git a/osu.Game.Rulesets.Taiko/Skinning/TaikoLegacySkinTransformer.cs b/osu.Game.Rulesets.Taiko/Skinning/TaikoLegacySkinTransformer.cs index 6e9a37eb93..23d675cfb0 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/TaikoLegacySkinTransformer.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/TaikoLegacySkinTransformer.cs @@ -6,23 +6,20 @@ using System.Collections.Generic; using osu.Framework.Audio.Sample; using osu.Framework.Bindables; using osu.Framework.Graphics; -using osu.Framework.Graphics.Textures; using osu.Game.Audio; using osu.Game.Rulesets.Taiko.UI; using osu.Game.Skinning; namespace osu.Game.Rulesets.Taiko.Skinning { - public class TaikoLegacySkinTransformer : ISkin + public class TaikoLegacySkinTransformer : LegacySkinTransformer { - private readonly ISkinSource source; - public TaikoLegacySkinTransformer(ISkinSource source) + : base(source) { - this.source = source; } - public Drawable GetDrawableComponent(ISkinComponent component) + public override Drawable GetDrawableComponent(ISkinComponent component) { if (!(component is TaikoSkinComponent taikoComponent)) return null; @@ -100,7 +97,7 @@ namespace osu.Game.Rulesets.Taiko.Skinning return null; } - return source.GetDrawableComponent(component); + return Source.GetDrawableComponent(component); } private string getHitName(TaikoSkinComponents component) @@ -120,11 +117,9 @@ namespace osu.Game.Rulesets.Taiko.Skinning throw new ArgumentOutOfRangeException(nameof(component), "Invalid result type"); } - public Texture GetTexture(string componentName) => source.GetTexture(componentName); + public override SampleChannel GetSample(ISampleInfo sampleInfo) => Source.GetSample(new LegacyTaikoSampleInfo(sampleInfo)); - public SampleChannel GetSample(ISampleInfo sampleInfo) => source.GetSample(new LegacyTaikoSampleInfo(sampleInfo)); - - public IBindable GetConfig(TLookup lookup) => source.GetConfig(lookup); + public override IBindable GetConfig(TLookup lookup) => Source.GetConfig(lookup); private class LegacyTaikoSampleInfo : ISampleInfo { diff --git a/osu.Game/Skinning/LegacySkinTransformer.cs b/osu.Game/Skinning/LegacySkinTransformer.cs new file mode 100644 index 0000000000..1131c93288 --- /dev/null +++ b/osu.Game/Skinning/LegacySkinTransformer.cs @@ -0,0 +1,35 @@ +// 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.Audio.Sample; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Textures; +using osu.Game.Audio; + +namespace osu.Game.Skinning +{ + /// + /// Transformer used to handle support of legacy features for individual rulesets. + /// + public abstract class LegacySkinTransformer : ISkin + { + /// + /// Source of the which is being transformed. + /// + protected ISkinSource Source { get; } + + protected LegacySkinTransformer(ISkinSource source) + { + Source = source; + } + + public abstract Drawable GetDrawableComponent(ISkinComponent component); + + public Texture GetTexture(string componentName) => Source.GetTexture(componentName); + + public virtual SampleChannel GetSample(ISampleInfo sampleInfo) => Source.GetSample(sampleInfo); + + public abstract IBindable GetConfig(TLookup lookup); + } +} From 1bc5f3618417a15fe1fd0f44e705e4911d5adacd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 21 Jun 2020 22:05:10 +0200 Subject: [PATCH 57/59] Adjust test usage --- osu.Game.Rulesets.Catch.Tests/CatchSkinColourDecodingTest.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch.Tests/CatchSkinColourDecodingTest.cs b/osu.Game.Rulesets.Catch.Tests/CatchSkinColourDecodingTest.cs index 7deeec527f..b570f090ca 100644 --- a/osu.Game.Rulesets.Catch.Tests/CatchSkinColourDecodingTest.cs +++ b/osu.Game.Rulesets.Catch.Tests/CatchSkinColourDecodingTest.cs @@ -17,7 +17,8 @@ namespace osu.Game.Rulesets.Catch.Tests { var store = new NamespacedResourceStore(new DllResourceStore(GetType().Assembly), "Resources/special-skin"); var rawSkin = new TestLegacySkin(new SkinInfo { Name = "special-skin" }, store); - var skin = new CatchLegacySkinTransformer(rawSkin); + var skinSource = new SkinProvidingContainer(rawSkin); + var skin = new CatchLegacySkinTransformer(skinSource); Assert.AreEqual(new Color4(232, 185, 35, 255), skin.GetConfig(CatchSkinColour.HyperDash)?.Value); Assert.AreEqual(new Color4(232, 74, 35, 255), skin.GetConfig(CatchSkinColour.HyperDashAfterImage)?.Value); From 2d121b4e3dd8f10bf70d2f6051167d848fdc4fef Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 22 Jun 2020 16:32:27 +0900 Subject: [PATCH 58/59] Simplify lookup fallback code --- osu.Game.Tournament/IPC/FileBasedIPC.cs | 32 +++++-------------------- 1 file changed, 6 insertions(+), 26 deletions(-) diff --git a/osu.Game.Tournament/IPC/FileBasedIPC.cs b/osu.Game.Tournament/IPC/FileBasedIPC.cs index a17491bf2d..42be6ea119 100644 --- a/osu.Game.Tournament/IPC/FileBasedIPC.cs +++ b/osu.Game.Tournament/IPC/FileBasedIPC.cs @@ -4,7 +4,6 @@ using System; using System.IO; using System.Linq; -using System.Collections.Generic; using JetBrains.Annotations; using Microsoft.Win32; using osu.Framework.Allocation; @@ -187,32 +186,13 @@ namespace osu.Game.Tournament.IPC [CanBeNull] private string findStablePath() { - string stableInstallPath = string.Empty; + var stableInstallPath = findFromEnvVar() ?? + findFromRegistry() ?? + findFromLocalAppData() ?? + findFromDotFolder(); - try - { - List> stableFindMethods = new List> - { - findFromEnvVar, - findFromRegistry, - findFromLocalAppData, - findFromDotFolder - }; - - foreach (var r in stableFindMethods) - { - stableInstallPath = r.Invoke(); - - if (stableInstallPath != null) - return stableInstallPath; - } - - return null; - } - finally - { - Logger.Log($"Stable path for tourney usage: {stableInstallPath}"); - } + Logger.Log($"Stable path for tourney usage: {stableInstallPath}"); + return stableInstallPath; } private string findFromEnvVar() From fc31d4962938dc29c22e43c63e403be0530c909d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 22 Jun 2020 16:34:04 +0900 Subject: [PATCH 59/59] try-catch registry lookup to avoid crashes on non-windows platforms --- osu.Game.Tournament/IPC/FileBasedIPC.cs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tournament/IPC/FileBasedIPC.cs b/osu.Game.Tournament/IPC/FileBasedIPC.cs index 42be6ea119..999ce61ac8 100644 --- a/osu.Game.Tournament/IPC/FileBasedIPC.cs +++ b/osu.Game.Tournament/IPC/FileBasedIPC.cs @@ -238,13 +238,19 @@ namespace osu.Game.Tournament.IPC { Logger.Log("Trying to find stable in registry"); - string stableInstallPath; + try + { + string stableInstallPath; - using (RegistryKey key = Registry.ClassesRoot.OpenSubKey("osu")) - stableInstallPath = key?.OpenSubKey(@"shell\open\command")?.GetValue(string.Empty).ToString().Split('"')[1].Replace("osu!.exe", ""); + using (RegistryKey key = Registry.ClassesRoot.OpenSubKey("osu")) + stableInstallPath = key?.OpenSubKey(@"shell\open\command")?.GetValue(string.Empty).ToString().Split('"')[1].Replace("osu!.exe", ""); - if (ipcFileExistsInDirectory(stableInstallPath)) - return stableInstallPath; + if (ipcFileExistsInDirectory(stableInstallPath)) + return stableInstallPath; + } + catch + { + } return null; }