From d8275c4f9ba8fb0e1cb94ad502626611832074c8 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 16 Jan 2018 18:20:46 +0900 Subject: [PATCH 1/9] Fix beatmap query not including beatmap files --- osu.Game/Beatmaps/BeatmapStore.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Beatmaps/BeatmapStore.cs b/osu.Game/Beatmaps/BeatmapStore.cs index 02564489ad..df71c5c0d0 100644 --- a/osu.Game/Beatmaps/BeatmapStore.cs +++ b/osu.Game/Beatmaps/BeatmapStore.cs @@ -156,6 +156,7 @@ namespace osu.Game.Beatmaps public IQueryable Beatmaps => GetContext().BeatmapInfo .Include(b => b.BeatmapSet).ThenInclude(s => s.Metadata) + .Include(b => b.BeatmapSet).ThenInclude(s => s.Files).ThenInclude(f => f.FileInfo) .Include(b => b.Metadata) .Include(b => b.Ruleset) .Include(b => b.BaseDifficulty); From 52b48f2b7e3f65db4ddd189f970975dbe4d1ae20 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 17 Jan 2018 15:21:49 +0900 Subject: [PATCH 2/9] Fix replays not correctly considering negative time diffs --- osu.Game/Rulesets/Scoring/ScoreStore.cs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/Scoring/ScoreStore.cs b/osu.Game/Rulesets/Scoring/ScoreStore.cs index fe366f52a5..83c365d53b 100644 --- a/osu.Game/Rulesets/Scoring/ScoreStore.cs +++ b/osu.Game/Rulesets/Scoring/ScoreStore.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Linq; using osu.Framework.Platform; using osu.Game.Beatmaps; using osu.Game.Database; @@ -129,7 +130,14 @@ namespace osu.Game.Rulesets.Scoring { var split = l.Split('|'); - if (split.Length < 4 || float.Parse(split[0]) < 0) continue; + if (split.Length < 4) + continue; + + if (split[0] == "-12345") + { + // Todo: The seed is provided in split[3], which we'll need to use at some point + continue; + } lastTime += float.Parse(split[0]); @@ -141,7 +149,7 @@ namespace osu.Game.Rulesets.Scoring )); } - return new Replay { Frames = frames }; + return new Replay { Frames = frames.OrderBy(f => f.Time).ToList() }; } } } From da793d91ea30414b7c62bee7254065f3bc1e70ff Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 17 Jan 2018 17:35:27 +0900 Subject: [PATCH 3/9] Make a testcase for replay vs autoplay --- osu.Game.Tests/Visual/TestCaseAutoplay.cs | 21 +++++++++++++++++++++ osu.Game.Tests/Visual/TestCaseReplay.cs | 18 +++++++++++++++++- osu.Game.Tests/osu.Game.Tests.csproj | 1 + 3 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 osu.Game.Tests/Visual/TestCaseAutoplay.cs diff --git a/osu.Game.Tests/Visual/TestCaseAutoplay.cs b/osu.Game.Tests/Visual/TestCaseAutoplay.cs new file mode 100644 index 0000000000..d954d0543c --- /dev/null +++ b/osu.Game.Tests/Visual/TestCaseAutoplay.cs @@ -0,0 +1,21 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.ComponentModel; +using System.Linq; +using osu.Game.Beatmaps; +using osu.Game.Rulesets; +using osu.Game.Screens.Play; + +namespace osu.Game.Tests.Visual +{ + [Description("Player instantiated with an autoplay mod.")] + public class TestCaseAutoplay : TestCasePlayer + { + protected override Player CreatePlayer(WorkingBeatmap beatmap, Ruleset ruleset) + { + beatmap.Mods.Value = beatmap.Mods.Value.Concat(new[] { ruleset.GetAutoplayMod() }); + return base.CreatePlayer(beatmap, ruleset); + } + } +} diff --git a/osu.Game.Tests/Visual/TestCaseReplay.cs b/osu.Game.Tests/Visual/TestCaseReplay.cs index 451c4e013f..237687458d 100644 --- a/osu.Game.Tests/Visual/TestCaseReplay.cs +++ b/osu.Game.Tests/Visual/TestCaseReplay.cs @@ -1,19 +1,35 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.ComponentModel; using System.Linq; using osu.Game.Beatmaps; using osu.Game.Rulesets; +using osu.Game.Rulesets.Mods; using osu.Game.Screens.Play; namespace osu.Game.Tests.Visual { + [Description("Player instantiated with a replay.")] public class TestCaseReplay : TestCasePlayer { protected override Player CreatePlayer(WorkingBeatmap beatmap, Ruleset ruleset) { + // We create a dummy RulesetContainer just to get the replay - we don't want to use mods here + // to simulate setting a replay rather than having the replay already set for us beatmap.Mods.Value = beatmap.Mods.Value.Concat(new[] { ruleset.GetAutoplayMod() }); - return base.CreatePlayer(beatmap, ruleset); + var dummyRulesetContainer = ruleset.CreateRulesetContainerWith(beatmap, false); + + // We have the replay + var replay = dummyRulesetContainer.Replay; + + // Reset the mods + beatmap.Mods.Value = beatmap.Mods.Value.Where(m => !(m is ModAutoplay)); + + return new ReplayPlayer(replay) + { + InitialBeatmap = beatmap + }; } } } diff --git a/osu.Game.Tests/osu.Game.Tests.csproj b/osu.Game.Tests/osu.Game.Tests.csproj index 2eb79f6b35..20148828a8 100644 --- a/osu.Game.Tests/osu.Game.Tests.csproj +++ b/osu.Game.Tests/osu.Game.Tests.csproj @@ -136,6 +136,7 @@ + From 2ebb3d6e0ed46b39baa03d6c95f1f3b29ff76b96 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 17 Jan 2018 17:37:14 +0900 Subject: [PATCH 4/9] Fix ReplayLoader not being treated as having a replay loaded Player checks for HasReplayLoaded in Player.load(), but the replay is attached in ReplayPlayer.LoadComplete(), which is too late. --- osu.Game/Rulesets/UI/RulesetContainer.cs | 7 ++++-- osu.Game/Screens/Play/HUDOverlay.cs | 32 ++++++++++++++++-------- osu.Game/Screens/Play/Player.cs | 3 +-- osu.Game/Screens/Play/SongProgress.cs | 13 ++++++++++ 4 files changed, 41 insertions(+), 14 deletions(-) diff --git a/osu.Game/Rulesets/UI/RulesetContainer.cs b/osu.Game/Rulesets/UI/RulesetContainer.cs index 626b56ad67..bb4466208b 100644 --- a/osu.Game/Rulesets/UI/RulesetContainer.cs +++ b/osu.Game/Rulesets/UI/RulesetContainer.cs @@ -13,6 +13,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; +using osu.Framework.Configuration; using osu.Framework.Graphics.Cursor; using osu.Framework.Input; using osu.Game.Rulesets.Replays; @@ -45,9 +46,9 @@ namespace osu.Game.Rulesets.UI public PassThroughInputManager KeyBindingInputManager; /// - /// Whether we have a replay loaded currently. + /// Whether a replay is currently loaded. /// - public bool HasReplayLoaded => ReplayInputManager?.ReplayInputHandler != null; + public readonly BindableBool HasReplayLoaded = new BindableBool(); public abstract IEnumerable Objects { get; } @@ -99,6 +100,8 @@ namespace osu.Game.Rulesets.UI Replay = replay; ReplayInputManager.ReplayInputHandler = replay != null ? CreateReplayInputHandler(replay) : null; + + HasReplayLoaded.Value = ReplayInputManager.ReplayInputHandler != null; } diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index 721b5344ff..95d13cea3a 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -35,7 +35,7 @@ namespace osu.Game.Screens.Play public readonly ReplaySettingsOverlay ReplaySettingsOverlay; private Bindable showHud; - private bool replayLoaded; + private readonly BindableBool replayLoaded = new BindableBool(); private static bool hasShownNotificationOnce; @@ -59,6 +59,24 @@ namespace osu.Game.Screens.Play ReplaySettingsOverlay = CreateReplaySettingsOverlay(), } }); + + replayLoaded.ValueChanged += replayLoadedValueChanged; + } + + private void replayLoadedValueChanged(bool loaded) + { + ReplaySettingsOverlay.ReplayLoaded = loaded; + + if (loaded) + { + ReplaySettingsOverlay.Show(); + ModDisplay.FadeIn(200); + } + else + { + ReplaySettingsOverlay.Hide(); + ModDisplay.Delay(2000).FadeOut(200); + } } [BackgroundDependencyLoader(true)] @@ -95,16 +113,10 @@ namespace osu.Game.Screens.Play { (rulesetContainer.KeyBindingInputManager as ICanAttachKeyCounter)?.Attach(KeyCounter); - replayLoaded = rulesetContainer.HasReplayLoaded; + replayLoaded.BindTo(rulesetContainer.HasReplayLoaded); + replayLoaded.TriggerChange(); - ReplaySettingsOverlay.ReplayLoaded = replayLoaded; - - // in the case a replay isn't loaded, we want some elements to only appear briefly. - if (!replayLoaded) - { - ReplaySettingsOverlay.Hide(); - ModDisplay.Delay(2000).FadeOut(200); - } + Progress.BindRulestContainer(rulesetContainer); } protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 31d9fac2ad..8d26d63d41 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -52,7 +52,7 @@ namespace osu.Game.Screens.Play public int RestartCount; public CursorContainer Cursor => RulesetContainer.Cursor; - public bool ProvidingUserCursor => RulesetContainer?.Cursor != null && !RulesetContainer.HasReplayLoaded; + public bool ProvidingUserCursor => RulesetContainer?.Cursor != null && !RulesetContainer.HasReplayLoaded.Value; private IAdjustableClock adjustableSourceClock; private FramedOffsetClock offsetClock; @@ -226,7 +226,6 @@ namespace osu.Game.Screens.Play hudOverlay.Progress.Objects = RulesetContainer.Objects; hudOverlay.Progress.AudioClock = decoupledClock; - hudOverlay.Progress.AllowSeeking = RulesetContainer.HasReplayLoaded; hudOverlay.Progress.OnSeek = pos => decoupledClock.Seek(pos); hudOverlay.ModDisplay.Current.BindTo(working.Mods); diff --git a/osu.Game/Screens/Play/SongProgress.cs b/osu.Game/Screens/Play/SongProgress.cs index 897fe4bba7..b367d33c6d 100644 --- a/osu.Game/Screens/Play/SongProgress.cs +++ b/osu.Game/Screens/Play/SongProgress.cs @@ -9,9 +9,12 @@ using System.Collections.Generic; using osu.Game.Graphics; using osu.Framework.Allocation; using System.Linq; +using osu.Framework.Configuration; using osu.Framework.Timing; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; +using osu.Game.Rulesets.UI; + namespace osu.Game.Screens.Play { public class SongProgress : OverlayContainer @@ -53,6 +56,8 @@ namespace osu.Game.Screens.Play } } + private readonly BindableBool replayLoaded = new BindableBool(); + [BackgroundDependencyLoader] private void load(OsuColour colours) { @@ -92,6 +97,8 @@ namespace osu.Game.Screens.Play OnSeek = position => OnSeek?.Invoke(position), }, }; + + replayLoaded.ValueChanged += v => AllowSeeking = v; } protected override void LoadComplete() @@ -99,6 +106,12 @@ namespace osu.Game.Screens.Play State = Visibility.Visible; } + public void BindRulestContainer(RulesetContainer rulesetContainer) + { + replayLoaded.BindTo(rulesetContainer.HasReplayLoaded); + replayLoaded.TriggerChange(); + } + private bool allowSeeking; public bool AllowSeeking From a01e46bb68b7510665000518667808565450df35 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 17 Jan 2018 17:55:55 +0900 Subject: [PATCH 5/9] Fix ScoreStore replays not getting users --- osu.Game/Rulesets/Scoring/ScoreStore.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Scoring/ScoreStore.cs b/osu.Game/Rulesets/Scoring/ScoreStore.cs index 83c365d53b..40a2bb34de 100644 --- a/osu.Game/Rulesets/Scoring/ScoreStore.cs +++ b/osu.Game/Rulesets/Scoring/ScoreStore.cs @@ -11,6 +11,7 @@ using osu.Game.Database; using osu.Game.IO.Legacy; using osu.Game.IPC; using osu.Game.Rulesets.Replays; +using osu.Game.Users; using SharpCompress.Compressors.LZMA; namespace osu.Game.Rulesets.Scoring @@ -55,7 +56,7 @@ namespace osu.Game.Rulesets.Scoring var beatmapHash = sr.ReadString(); score.Beatmap = beatmaps.QueryBeatmap(b => b.MD5Hash == beatmapHash); /* score.PlayerName = */ - sr.ReadString(); + score.User = new User { Username = sr.ReadString() }; /* var localScoreChecksum = */ sr.ReadString(); /* score.Count300 = */ @@ -108,7 +109,10 @@ namespace osu.Game.Rulesets.Scoring using (var lzma = new LzmaStream(properties, replayInStream, compressedSize, outSize)) using (var reader = new StreamReader(lzma)) + { score.Replay = createLegacyReplay(reader); + score.Replay.User = score.User; + } } } From da22b3ec49eb17b4eae275d1f2006e4197839320 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 17 Jan 2018 20:12:39 +0900 Subject: [PATCH 6/9] No more sorting --- osu.Game/Rulesets/Scoring/ScoreStore.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/osu.Game/Rulesets/Scoring/ScoreStore.cs b/osu.Game/Rulesets/Scoring/ScoreStore.cs index 40a2bb34de..b7385b9437 100644 --- a/osu.Game/Rulesets/Scoring/ScoreStore.cs +++ b/osu.Game/Rulesets/Scoring/ScoreStore.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using System.IO; -using System.Linq; using osu.Framework.Platform; using osu.Game.Beatmaps; using osu.Game.Database; @@ -143,7 +142,11 @@ namespace osu.Game.Rulesets.Scoring continue; } - lastTime += float.Parse(split[0]); + var diff = float.Parse(split[0]); + lastTime += diff; + + if (diff < 0) + continue; frames.Add(new ReplayFrame( lastTime, @@ -153,7 +156,7 @@ namespace osu.Game.Rulesets.Scoring )); } - return new Replay { Frames = frames.OrderBy(f => f.Time).ToList() }; + return new Replay { Frames = frames }; } } } From 379688e2f25ee31e34aec34bf3a2d042e682855e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 17 Jan 2018 20:15:17 +0900 Subject: [PATCH 7/9] Add todo --- osu.Game/Rulesets/Scoring/ScoreStore.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Rulesets/Scoring/ScoreStore.cs b/osu.Game/Rulesets/Scoring/ScoreStore.cs index b7385b9437..d21ca79736 100644 --- a/osu.Game/Rulesets/Scoring/ScoreStore.cs +++ b/osu.Game/Rulesets/Scoring/ScoreStore.cs @@ -145,6 +145,8 @@ namespace osu.Game.Rulesets.Scoring var diff = float.Parse(split[0]); lastTime += diff; + // Todo: At some point we probably want to rewind and play back the negative-time frames + // but for now we'll achieve equal playback to stable by skipping negative frames if (diff < 0) continue; From c79603290d2f53ecd9bf2511074df72feeb6a05d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 17 Jan 2018 21:52:57 +0900 Subject: [PATCH 8/9] Move TriggerChange to LoadComplete() --- osu.Game/Screens/Play/HUDOverlay.cs | 42 +++++++++++++++------------ osu.Game/Screens/Play/SongProgress.cs | 4 ++- 2 files changed, 27 insertions(+), 19 deletions(-) diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index 95d13cea3a..413d46f66e 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -60,23 +60,6 @@ namespace osu.Game.Screens.Play } }); - replayLoaded.ValueChanged += replayLoadedValueChanged; - } - - private void replayLoadedValueChanged(bool loaded) - { - ReplaySettingsOverlay.ReplayLoaded = loaded; - - if (loaded) - { - ReplaySettingsOverlay.Show(); - ModDisplay.FadeIn(200); - } - else - { - ReplaySettingsOverlay.Hide(); - ModDisplay.Delay(2000).FadeOut(200); - } } [BackgroundDependencyLoader(true)] @@ -109,12 +92,35 @@ namespace osu.Game.Screens.Play } } + protected override void LoadComplete() + { + base.LoadComplete(); + + replayLoaded.ValueChanged += replayLoadedValueChanged; + replayLoaded.TriggerChange(); + } + + private void replayLoadedValueChanged(bool loaded) + { + ReplaySettingsOverlay.ReplayLoaded = loaded; + + if (loaded) + { + ReplaySettingsOverlay.Show(); + ModDisplay.FadeIn(200); + } + else + { + ReplaySettingsOverlay.Hide(); + ModDisplay.Delay(2000).FadeOut(200); + } + } + public virtual void BindRulesetContainer(RulesetContainer rulesetContainer) { (rulesetContainer.KeyBindingInputManager as ICanAttachKeyCounter)?.Attach(KeyCounter); replayLoaded.BindTo(rulesetContainer.HasReplayLoaded); - replayLoaded.TriggerChange(); Progress.BindRulestContainer(rulesetContainer); } diff --git a/osu.Game/Screens/Play/SongProgress.cs b/osu.Game/Screens/Play/SongProgress.cs index 2681d9a353..323635b4d6 100644 --- a/osu.Game/Screens/Play/SongProgress.cs +++ b/osu.Game/Screens/Play/SongProgress.cs @@ -105,12 +105,14 @@ namespace osu.Game.Screens.Play protected override void LoadComplete() { State = Visibility.Visible; + + replayLoaded.ValueChanged += v => AllowSeeking = v; + replayLoaded.TriggerChange(); } public void BindRulestContainer(RulesetContainer rulesetContainer) { replayLoaded.BindTo(rulesetContainer.HasReplayLoaded); - replayLoaded.TriggerChange(); } private bool allowSeeking; From a05032779ffa6073f026839f4ad2b658f3daebec Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 18 Jan 2018 00:03:41 +0900 Subject: [PATCH 9/9] Remove unneeded event binding --- osu.Game/Screens/Play/HUDOverlay.cs | 1 - osu.Game/Screens/Play/SongProgress.cs | 2 -- 2 files changed, 3 deletions(-) diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index 413d46f66e..255c071ac1 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -59,7 +59,6 @@ namespace osu.Game.Screens.Play ReplaySettingsOverlay = CreateReplaySettingsOverlay(), } }); - } [BackgroundDependencyLoader(true)] diff --git a/osu.Game/Screens/Play/SongProgress.cs b/osu.Game/Screens/Play/SongProgress.cs index 323635b4d6..12f501a632 100644 --- a/osu.Game/Screens/Play/SongProgress.cs +++ b/osu.Game/Screens/Play/SongProgress.cs @@ -98,8 +98,6 @@ namespace osu.Game.Screens.Play OnSeek = position => OnSeek?.Invoke(position), }, }; - - replayLoaded.ValueChanged += v => AllowSeeking = v; } protected override void LoadComplete()