From 3b52e7c72408555fbf6d42d988033ef30bac7f0e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 22 Sep 2019 02:10:04 +0900 Subject: [PATCH 1/6] Add boilerplate logic --- .../Screens/TestSceneSetupScreen.cs | 17 +++++++++++++++++ osu.Game.Tournament/Screens/SetupScreen.cs | 9 +++++++++ osu.Game.Tournament/TournamentSceneManager.cs | 2 ++ 3 files changed, 28 insertions(+) create mode 100644 osu.Game.Tournament.Tests/Screens/TestSceneSetupScreen.cs create mode 100644 osu.Game.Tournament/Screens/SetupScreen.cs diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneSetupScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneSetupScreen.cs new file mode 100644 index 0000000000..650b4c5412 --- /dev/null +++ b/osu.Game.Tournament.Tests/Screens/TestSceneSetupScreen.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 osu.Framework.Allocation; +using osu.Game.Tournament.Screens; + +namespace osu.Game.Tournament.Tests.Screens +{ + public class TestSceneSetupScreen : TournamentTestScene + { + [BackgroundDependencyLoader] + private void load() + { + Add(new SetupScreen()); + } + } +} diff --git a/osu.Game.Tournament/Screens/SetupScreen.cs b/osu.Game.Tournament/Screens/SetupScreen.cs new file mode 100644 index 0000000000..a5e0e5927a --- /dev/null +++ b/osu.Game.Tournament/Screens/SetupScreen.cs @@ -0,0 +1,9 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +namespace osu.Game.Tournament.Screens +{ + public class SetupScreen : TournamentScreen + { + } +} diff --git a/osu.Game.Tournament/TournamentSceneManager.cs b/osu.Game.Tournament/TournamentSceneManager.cs index 4c255be463..b1384023d3 100644 --- a/osu.Game.Tournament/TournamentSceneManager.cs +++ b/osu.Game.Tournament/TournamentSceneManager.cs @@ -106,6 +106,8 @@ namespace osu.Game.Tournament Direction = FillDirection.Vertical, Children = new Drawable[] { + new OsuButton { RelativeSizeAxes = Axes.X, Text = "Setup", Action = () => SetScreen(typeof(SetupScreen)) }, + new Container { RelativeSizeAxes = Axes.X, Height = 50 }, new OsuButton { RelativeSizeAxes = Axes.X, Text = "Team Editor", Action = () => SetScreen(typeof(TeamEditorScreen)) }, new OsuButton { RelativeSizeAxes = Axes.X, Text = "Rounds Editor", Action = () => SetScreen(typeof(RoundEditorScreen)) }, new OsuButton { RelativeSizeAxes = Axes.X, Text = "Bracket Editor", Action = () => SetScreen(typeof(LadderEditorScreen)) }, From 47a89231ad3da90ca774fb524a75cd61c68a4bbd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 22 Sep 2019 04:15:02 +0900 Subject: [PATCH 2/6] Read from (and allow reloading) IPC source --- osu.Game.Tournament/IPC/FileBasedIPC.cs | 186 +++++++++++---------- osu.Game.Tournament/Screens/SetupScreen.cs | 15 ++ 2 files changed, 117 insertions(+), 84 deletions(-) diff --git a/osu.Game.Tournament/IPC/FileBasedIPC.cs b/osu.Game.Tournament/IPC/FileBasedIPC.cs index 4fd858bd12..e05d96e098 100644 --- a/osu.Game.Tournament/IPC/FileBasedIPC.cs +++ b/osu.Game.Tournament/IPC/FileBasedIPC.cs @@ -9,6 +9,7 @@ using osu.Framework.Allocation; using osu.Framework.Logging; using osu.Framework.Platform; using osu.Framework.Platform.Windows; +using osu.Framework.Threading; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Legacy; using osu.Game.Online.API; @@ -26,103 +27,120 @@ namespace osu.Game.Tournament.IPC [Resolved] protected RulesetStore Rulesets { get; private set; } + [Resolved] + private GameHost host { get; set; } + + [Resolved] + private LadderInfo ladder { get; set; } + private int lastBeatmapId; + private ScheduledDelegate scheduled; + + public Storage Storage { get; private set; } [BackgroundDependencyLoader] - private void load(LadderInfo ladder, GameHost host) + private void load() { - StableStorage stable; + LocateStableStorage(); + } + + public Storage LocateStableStorage() + { + scheduled?.Cancel(); + + Storage = null; try { - stable = new StableStorage(host as DesktopGameHost); + Storage = new StableStorage(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)) + scheduled = Scheduler.AddDelayed(delegate + { + try + { + using (var stream = Storage.GetStream(file_ipc_filename)) + using (var sr = new StreamReader(stream)) + { + var beatmapId = int.Parse(sr.ReadLine()); + var mods = int.Parse(sr.ReadLine()); + + if (lastBeatmapId != beatmapId) + { + lastBeatmapId = beatmapId; + + var existing = ladder.CurrentMatch.Value?.Round.Value?.Beatmaps.FirstOrDefault(b => b.ID == beatmapId && b.BeatmapInfo != null); + + if (existing != null) + Beatmap.Value = existing.BeatmapInfo; + else + { + var req = new GetBeatmapRequest(new BeatmapInfo { OnlineBeatmapID = beatmapId }); + req.Success += b => Beatmap.Value = b.ToBeatmap(Rulesets); + API.Queue(req); + } + } + + Mods.Value = (LegacyMods)mods; + } + } + catch + { + // file might be in use. + } + + try + { + using (var stream = Storage.GetStream(file_ipc_channel_filename)) + using (var sr = new StreamReader(stream)) + { + ChatChannel.Value = sr.ReadLine(); + } + } + catch (Exception) + { + // file might be in use. + } + + try + { + using (var stream = Storage.GetStream(file_ipc_state_filename)) + using (var sr = new StreamReader(stream)) + { + State.Value = (TourneyState)Enum.Parse(typeof(TourneyState), sr.ReadLine()); + } + } + catch (Exception) + { + // file might be in use. + } + + try + { + using (var stream = Storage.GetStream(file_ipc_scores_filename)) + using (var sr = new StreamReader(stream)) + { + Score1.Value = int.Parse(sr.ReadLine()); + Score2.Value = int.Parse(sr.ReadLine()); + } + } + catch (Exception) + { + // file might be in use. + } + }, 250, true); } catch (Exception e) { Logger.Error(e, "Stable installation could not be found; disabling file based IPC"); - return; } - 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 (stable.Exists(file_ipc_filename)) - Scheduler.AddDelayed(delegate - { - try - { - using (var stream = stable.GetStream(file_ipc_filename)) - using (var sr = new StreamReader(stream)) - { - var beatmapId = int.Parse(sr.ReadLine()); - var mods = int.Parse(sr.ReadLine()); - - if (lastBeatmapId != beatmapId) - { - lastBeatmapId = beatmapId; - - var existing = ladder.CurrentMatch.Value?.Round.Value?.Beatmaps.FirstOrDefault(b => b.ID == beatmapId && b.BeatmapInfo != null); - - if (existing != null) - Beatmap.Value = existing.BeatmapInfo; - else - { - var req = new GetBeatmapRequest(new BeatmapInfo { OnlineBeatmapID = beatmapId }); - req.Success += b => Beatmap.Value = b.ToBeatmap(Rulesets); - API.Queue(req); - } - } - - Mods.Value = (LegacyMods)mods; - } - } - catch - { - // file might be in use. - } - - try - { - using (var stream = stable.GetStream(file_ipc_channel_filename)) - using (var sr = new StreamReader(stream)) - { - ChatChannel.Value = sr.ReadLine(); - } - } - catch (Exception) - { - // file might be in use. - } - - try - { - using (var stream = stable.GetStream(file_ipc_state_filename)) - using (var sr = new StreamReader(stream)) - { - State.Value = (TourneyState)Enum.Parse(typeof(TourneyState), sr.ReadLine()); - } - } - catch (Exception) - { - // file might be in use. - } - - try - { - using (var stream = stable.GetStream(file_ipc_scores_filename)) - using (var sr = new StreamReader(stream)) - { - Score1.Value = int.Parse(sr.ReadLine()); - Score2.Value = int.Parse(sr.ReadLine()); - } - } - catch (Exception) - { - // file might be in use. - } - }, 250, true); + return Storage; } /// diff --git a/osu.Game.Tournament/Screens/SetupScreen.cs b/osu.Game.Tournament/Screens/SetupScreen.cs index a5e0e5927a..b75b0056ce 100644 --- a/osu.Game.Tournament/Screens/SetupScreen.cs +++ b/osu.Game.Tournament/Screens/SetupScreen.cs @@ -1,9 +1,24 @@ // 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.Graphics.Sprites; +using osu.Game.Tournament.IPC; + namespace osu.Game.Tournament.Screens { public class SetupScreen : TournamentScreen { + [Resolved] + private MatchIPCInfo ipc { get; set; } + + [BackgroundDependencyLoader] + private void load() + { + AddInternal(new SpriteText + { + Text = (ipc as FileBasedIPC)?.Storage.GetFullPath(string.Empty) + }); + } } } From e07aa94fc8701f0a2807ef04cbca20d26f75566c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 23 Sep 2019 04:22:50 +0900 Subject: [PATCH 3/6] Allow reloading ipc source --- osu.Game.Tournament/Screens/SetupScreen.cs | 84 ++++++++++++++++++++-- 1 file changed, 80 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tournament/Screens/SetupScreen.cs b/osu.Game.Tournament/Screens/SetupScreen.cs index b75b0056ce..992762431e 100644 --- a/osu.Game.Tournament/Screens/SetupScreen.cs +++ b/osu.Game.Tournament/Screens/SetupScreen.cs @@ -1,9 +1,16 @@ // 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.Allocation; -using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; +using osu.Game.Screens.Edit.Setup.Components.LabelledComponents; using osu.Game.Tournament.IPC; +using osuTK; +using osuTK.Graphics; namespace osu.Game.Tournament.Screens { @@ -15,10 +22,79 @@ namespace osu.Game.Tournament.Screens [BackgroundDependencyLoader] private void load() { - AddInternal(new SpriteText + reload(); + } + + private void reload() + { + var fileBasedIpc = ipc as FileBasedIPC; + + InternalChildren = new Drawable[] { - Text = (ipc as FileBasedIPC)?.Storage.GetFullPath(string.Empty) - }); + new ActionableInfo + { + Label = "Current IPC source", + ButtonText = "Refresh", + Action = () => + { + fileBasedIpc?.LocateStableStorage(); + reload(); + }, + Value = fileBasedIpc?.Storage?.GetFullPath(string.Empty) ?? "Not found", + Failing = fileBasedIpc?.Storage == 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." + } + }; + } + + private class ActionableInfo : LabelledComponent + { + private OsuButton button; + + public ActionableInfo() + : base(true) + { + } + + public string ButtonText + { + set => button.Text = value; + } + + public string Value + { + set => valueText.Text = value; + } + + public bool Failing + { + set => valueText.Colour = value ? Color4.Red : Color4.White; + } + + public Action Action; + + private OsuSpriteText valueText; + + protected override Drawable CreateComponent() => new Container + { + AutoSizeAxes = Axes.Y, + RelativeSizeAxes = Axes.X, + Children = new Drawable[] + { + valueText = new OsuSpriteText + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + }, + button = new TriangleButton + { + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + Size = new Vector2(100, 30), + Action = () => Action?.Invoke() + }, + } + }; } } } From b41ac543c5a4a4d31e783a4c802f80d25871a427 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 23 Sep 2019 04:45:23 +0900 Subject: [PATCH 4/6] Allow changing logged in user --- osu.Game.Tournament/Screens/SetupScreen.cs | 44 ++++++++++++++++++- osu.Game.Tournament/TournamentSceneManager.cs | 1 + .../Sections/General/LoginSettings.cs | 4 +- 3 files changed, 46 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tournament/Screens/SetupScreen.cs b/osu.Game.Tournament/Screens/SetupScreen.cs index 992762431e..8ccb469b13 100644 --- a/osu.Game.Tournament/Screens/SetupScreen.cs +++ b/osu.Game.Tournament/Screens/SetupScreen.cs @@ -7,6 +7,8 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; +using osu.Game.Online.API; +using osu.Game.Overlays; using osu.Game.Screens.Edit.Setup.Components.LabelledComponents; using osu.Game.Tournament.IPC; using osuTK; @@ -16,12 +18,29 @@ namespace osu.Game.Tournament.Screens { public class SetupScreen : TournamentScreen { + private FillFlowContainer fillFlow; + + private LoginOverlay loginOverlay; + [Resolved] private MatchIPCInfo ipc { get; set; } + [Resolved] + private IAPIProvider api { get; set; } + [BackgroundDependencyLoader] private void load() { + InternalChild = fillFlow = new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Padding = new MarginPadding(10), + Spacing = new Vector2(10), + }; + + api.LocalUser.BindValueChanged(_ => Schedule(reload)); reload(); } @@ -29,7 +48,7 @@ namespace osu.Game.Tournament.Screens { var fileBasedIpc = ipc as FileBasedIPC; - InternalChildren = new Drawable[] + fillFlow.Children = new Drawable[] { new ActionableInfo { @@ -43,6 +62,29 @@ namespace osu.Game.Tournament.Screens Value = fileBasedIpc?.Storage?.GetFullPath(string.Empty) ?? "Not found", Failing = fileBasedIpc?.Storage == 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 = "Current User", + ButtonText = "Change Login", + Action = () => + { + api.Logout(); + + if (loginOverlay == null) + { + AddInternal(loginOverlay = new LoginOverlay() + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + }); + } + + loginOverlay.State.Value = Visibility.Visible; + }, + Value = api?.LocalUser.Value.Username, + Failing = api?.IsLoggedIn != true, + Description = "In order to access the API and display metadata, a login is required." } }; } diff --git a/osu.Game.Tournament/TournamentSceneManager.cs b/osu.Game.Tournament/TournamentSceneManager.cs index b1384023d3..58c6e3fee6 100644 --- a/osu.Game.Tournament/TournamentSceneManager.cs +++ b/osu.Game.Tournament/TournamentSceneManager.cs @@ -69,6 +69,7 @@ namespace osu.Game.Tournament RelativeSizeAxes = Axes.Both, Children = new Drawable[] { + new SetupScreen(), new ScheduleScreen(), new LadderScreen(), new LadderEditorScreen(), diff --git a/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs b/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs index 66fec1ecf9..b02b1a5489 100644 --- a/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs @@ -67,7 +67,7 @@ namespace osu.Game.Overlays.Settings.Sections.General api?.Register(this); } - public void APIStateChanged(IAPIProvider api, APIState state) + public void APIStateChanged(IAPIProvider api, APIState state) => Schedule(() => { form = null; @@ -184,7 +184,7 @@ namespace osu.Game.Overlays.Settings.Sections.General } if (form != null) GetContainingInputManager()?.ChangeFocus(form); - } + }); public override bool AcceptsFocus => true; From 4b7a42119119bbfdb03f7a458572a938714fdd30 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 23 Sep 2019 04:47:51 +0900 Subject: [PATCH 5/6] Set setup screen as default when opening --- osu.Game.Tournament/TournamentSceneManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tournament/TournamentSceneManager.cs b/osu.Game.Tournament/TournamentSceneManager.cs index 58c6e3fee6..02ee1c8603 100644 --- a/osu.Game.Tournament/TournamentSceneManager.cs +++ b/osu.Game.Tournament/TournamentSceneManager.cs @@ -130,7 +130,7 @@ namespace osu.Game.Tournament }, }; - SetScreen(typeof(ScheduleScreen)); + SetScreen(typeof(SetupScreen)); } public void SetScreen(Type screenType) From bafb429e9b6ae8ddaf120089f0bf6e845d7c3fc2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 23 Sep 2019 04:49:21 +0900 Subject: [PATCH 6/6] Don't show video background --- osu.Game.Tournament/Screens/SetupScreen.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tournament/Screens/SetupScreen.cs b/osu.Game.Tournament/Screens/SetupScreen.cs index 8ccb469b13..1cb4917790 100644 --- a/osu.Game.Tournament/Screens/SetupScreen.cs +++ b/osu.Game.Tournament/Screens/SetupScreen.cs @@ -16,7 +16,7 @@ using osuTK.Graphics; namespace osu.Game.Tournament.Screens { - public class SetupScreen : TournamentScreen + public class SetupScreen : TournamentScreen, IProvideVideo { private FillFlowContainer fillFlow; @@ -73,7 +73,7 @@ namespace osu.Game.Tournament.Screens if (loginOverlay == null) { - AddInternal(loginOverlay = new LoginOverlay() + AddInternal(loginOverlay = new LoginOverlay { Anchor = Anchor.TopRight, Origin = Anchor.TopRight,