From b9ab034f94d00d9341e54a3df28e8d9a34d02f70 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 15 Sep 2017 19:32:46 +0900 Subject: [PATCH 01/24] Fix catcher movement speed being way too slow Now matches osu-stable --- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 5fc2cf9ef7..f6563c4670 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -139,16 +139,21 @@ namespace osu.Game.Rulesets.Catch.UI return false; } + /// + /// The relative space to cover in 1 millisecond. based on 1 game pixel per millisecond as in osu-stable. + /// + private const double base_speed = 1.0 / 512; + protected override void Update() { base.Update(); if (currentDirection == 0) return; - float speed = Dashing ? 1.5f : 1; + double dashModifier = Dashing ? 1 : 0.5; Scale = new Vector2(Math.Sign(currentDirection), 1); - X = (float)MathHelper.Clamp(X + Math.Sign(currentDirection) * Clock.ElapsedFrameTime / 1800 * speed, 0, 1); + X = (float)MathHelper.Clamp(X + Math.Sign(currentDirection) * Clock.ElapsedFrameTime * base_speed * dashModifier, 0, 1); } public void AddToStack(DrawableHitObject fruit, Vector2 absolutePosition) From 4e0aed4b8a9b2d473f398893f1798dcac1616291 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 15 Sep 2017 20:54:34 +0900 Subject: [PATCH 02/24] Add combo/colour metadata to CatchBaseHit --- .../Beatmaps/CatchBeatmapConverter.cs | 1 + .../Beatmaps/CatchBeatmapProcessor.cs | 36 +++++++++++++++++++ .../Objects/CatchBaseHit.cs | 11 ++++++ .../UI/CatchRulesetContainer.cs | 2 ++ .../osu.Game.Rulesets.Catch.csproj | 1 + 5 files changed, 51 insertions(+) create mode 100644 osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs index d6efe45adf..fb9e93ceea 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs @@ -24,6 +24,7 @@ namespace osu.Game.Rulesets.Catch.Beatmaps yield return new Fruit { StartTime = obj.StartTime, + NewCombo = (obj as IHasCombo)?.NewCombo ?? false, Position = ((IHasXPosition)obj).X / OsuPlayfield.BASE_SIZE.X }; } diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs new file mode 100644 index 0000000000..b5e709885b --- /dev/null +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs @@ -0,0 +1,36 @@ +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Beatmaps; +using osu.Game.Rulesets.Catch.Objects; + +namespace osu.Game.Rulesets.Catch.Beatmaps +{ + internal class CatchBeatmapProcessor : BeatmapProcessor + { + public override void PostProcess(Beatmap beatmap) + { + if (beatmap.ComboColors.Count == 0) + return; + + int comboIndex = 0; + int colourIndex = 0; + + CatchBaseHit lastObj = null; + + foreach (var obj in beatmap.HitObjects) + { + if (obj.NewCombo) + { + if (lastObj != null) lastObj.LastInCombo = true; + + comboIndex = 0; + colourIndex = (colourIndex + 1) % beatmap.ComboColors.Count; + } + + obj.ComboIndex = comboIndex++; + obj.ComboColour = beatmap.ComboColors[colourIndex]; + + lastObj = obj; + } + } + } +} diff --git a/osu.Game.Rulesets.Catch/Objects/CatchBaseHit.cs b/osu.Game.Rulesets.Catch/Objects/CatchBaseHit.cs index de0547580f..42b50a3867 100644 --- a/osu.Game.Rulesets.Catch/Objects/CatchBaseHit.cs +++ b/osu.Game.Rulesets.Catch/Objects/CatchBaseHit.cs @@ -2,11 +2,22 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Rulesets.Objects; +using OpenTK.Graphics; namespace osu.Game.Rulesets.Catch.Objects { public abstract class CatchBaseHit : HitObject { public float Position { get; set; } + + public Color4 ComboColour { get; set; } = Color4.Gray; + public int ComboIndex { get; set; } + + public virtual bool NewCombo { get; set; } + + /// + /// The next fruit starts a new combo. Used for explodey. + /// + public virtual bool LastInCombo { get; set; } } } diff --git a/osu.Game.Rulesets.Catch/UI/CatchRulesetContainer.cs b/osu.Game.Rulesets.Catch/UI/CatchRulesetContainer.cs index 8f332bdcbf..879cba26c3 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchRulesetContainer.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchRulesetContainer.cs @@ -23,6 +23,8 @@ namespace osu.Game.Rulesets.Catch.UI public override ScoreProcessor CreateScoreProcessor() => new CatchScoreProcessor(this); + protected override BeatmapProcessor CreateBeatmapProcessor() => new CatchBeatmapProcessor(); + protected override BeatmapConverter CreateBeatmapConverter() => new CatchBeatmapConverter(); protected override Playfield CreatePlayfield() => new CatchPlayfield(); diff --git a/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj index 18e1ee29ca..8966b07a4a 100644 --- a/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj +++ b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj @@ -50,6 +50,7 @@ + From 8ccbc07dec64a72ce9a0bf7ed780ec75f6236ae8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 15 Sep 2017 20:54:46 +0900 Subject: [PATCH 03/24] Remove unnecessary constructor --- osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs index d299faaae2..50239bf16c 100644 --- a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs +++ b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs @@ -16,10 +16,6 @@ namespace osu.Game.Rulesets.Osu.Scoring { internal class OsuScoreProcessor : ScoreProcessor { - public OsuScoreProcessor() - { - } - public OsuScoreProcessor(RulesetContainer rulesetContainer) : base(rulesetContainer) { From fe221905faf09844c7812fdebb3c7212e4e48e99 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 15 Sep 2017 20:55:04 +0900 Subject: [PATCH 04/24] Make fruits look a bit closer to the final design --- .../Objects/Drawable/DrawableFruit.cs | 37 ++++++++++++++----- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs index 3dd086fb48..9d07c9d8dd 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs @@ -18,7 +18,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable { public class DrawableFruit : DrawableScrollingHitObject { - private const float pulp_size = 30; + private const float pulp_size = 20; private class Pulp : Circle, IHasAccentColour { @@ -26,15 +26,26 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable { Size = new Vector2(pulp_size); - EdgeEffect = new EdgeEffectParameters - { - Type = EdgeEffectType.Glow, - Radius = 5, - Colour = AccentColour.Opacity(0.5f), - }; + Blending = BlendingMode.Additive; + Colour = Color4.White.Opacity(0.9f); } - public Color4 AccentColour { get; set; } = Color4.White; + private Color4 accentColour; + public Color4 AccentColour + { + get { return accentColour; } + set + { + accentColour = value; + + EdgeEffect = new EdgeEffectParameters + { + Type = EdgeEffectType.Glow, + Radius = 5, + Colour = accentColour.Lighten(100), + }; + } + } } @@ -42,12 +53,14 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable : base(h) { Origin = Anchor.Centre; - Size = new Vector2(pulp_size * 2, pulp_size * 2.6f); + Size = new Vector2(pulp_size * 2.2f, pulp_size * 2.8f); RelativePositionAxes = Axes.Both; X = h.Position; - Colour = new Color4(RNG.NextSingle(), RNG.NextSingle(), RNG.NextSingle(), 1); + AccentColour = HitObject.ComboColour; + + Masking = false; Rotation = (float)(RNG.NextDouble() - 0.5f) * 40; } @@ -71,6 +84,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable RelativePositionAxes = Axes.Both, Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, + AccentColour = AccentColour, Scale = new Vector2(0.6f), }, new Pulp @@ -78,6 +92,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable RelativePositionAxes = Axes.Both, Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, + AccentColour = AccentColour, Y = -0.08f }, new Pulp @@ -85,6 +100,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable RelativePositionAxes = Axes.Both, Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, + AccentColour = AccentColour, Y = -0.08f }, new Pulp @@ -92,6 +108,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable RelativePositionAxes = Axes.Both, Anchor = Anchor.BottomCentre, Origin = Anchor.BottomCentre, + AccentColour = AccentColour, }, } } From cfcb0c1c6eec4d3ba8d01bd0943dd32745a0dc07 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 15 Sep 2017 21:26:36 +0900 Subject: [PATCH 05/24] Add (incorrectly) exploding fruit --- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 41 ++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index f6563c4670..5a1a1dddc4 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -20,6 +20,7 @@ namespace osu.Game.Rulesets.Catch.UI public class CatcherArea : Container { private Catcher catcher; + private Container explodingFruitContainer; public void Add(DrawableHitObject fruit, Vector2 screenPosition) => catcher.AddToStack(fruit, screenPosition); @@ -30,9 +31,14 @@ namespace osu.Game.Rulesets.Catch.UI { Children = new Drawable[] { + explodingFruitContainer = new Container + { + RelativeSizeAxes = Axes.Both, + }, catcher = new Catcher { RelativePositionAxes = Axes.Both, + ExplodingFruitTarget = explodingFruitContainer, Anchor = Anchor.TopLeft, Origin = Anchor.TopCentre, X = 0.5f, @@ -63,6 +69,8 @@ namespace osu.Game.Rulesets.Catch.UI private bool dashing; + public Container ExplodingFruitTarget; + protected bool Dashing { get { return dashing; } @@ -168,13 +176,44 @@ namespace osu.Game.Rulesets.Catch.UI float distance = fruit.DrawSize.X / 2 * fruit.Scale.X; - while (Children.OfType().Any(f => Vector2Extensions.DistanceSquared(f.Position, fruit.Position) < distance * distance)) + while (Children.OfType().Any(f => f.LifetimeEnd == double.PositiveInfinity && Vector2Extensions.DistanceSquared(f.Position, fruit.Position) < distance * distance)) { fruit.X += RNG.Next(-5, 5); fruit.Y -= RNG.Next(0, 5); } Add(fruit); + + if (((CatchBaseHit)fruit.HitObject).LastInCombo) + explode(); + } + + private void explode() + { + foreach (var existingFruit in Children.OfType().ToArray()) + { + var originalX = existingFruit.X * Scale.X; + + if (ExplodingFruitTarget != null) + { + existingFruit.Anchor = Anchor.TopLeft; + existingFruit.Position = ToSpaceOfOtherDrawable(existingFruit.DrawPosition, ExplodingFruitTarget); + + Remove(existingFruit); + + ExplodingFruitTarget.Add(existingFruit); + } + + existingFruit + .MoveToY(existingFruit.Y - 50, 250, Easing.OutSine) + .Then() + .MoveToY(existingFruit.Y + 50, 500, Easing.InSine); + + existingFruit.MoveToX(existingFruit.X + originalX * 6, 1000); + existingFruit.FadeOut(750); + + existingFruit.Expire(); + } } } } From e52a4fe72c3a290a67c848350de302c4ee68f63f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 18 Sep 2017 12:33:01 +0900 Subject: [PATCH 06/24] Put caught fruit in their own container to reduce casting --- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 46 ++++++++++++++--------- 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 5a1a1dddc4..dad9cd2715 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -11,7 +11,6 @@ using osu.Framework.Graphics.Textures; using osu.Framework.Input.Bindings; using osu.Framework.MathUtils; using osu.Game.Rulesets.Catch.Objects; -using osu.Game.Rulesets.Catch.Objects.Drawable; using osu.Game.Rulesets.Objects.Drawables; using OpenTK; @@ -39,7 +38,6 @@ namespace osu.Game.Rulesets.Catch.UI { RelativePositionAxes = Axes.Both, ExplodingFruitTarget = explodingFruitContainer, - Anchor = Anchor.TopLeft, Origin = Anchor.TopCentre, X = 0.5f, } @@ -57,12 +55,22 @@ namespace osu.Game.Rulesets.Catch.UI { private Texture texture; + private Container caughtFruit; + [BackgroundDependencyLoader] private void load(TextureStore textures) { texture = textures.Get(@"Play/Catch/fruit-catcher-idle"); - Child = createCatcherSprite(); + Children = new Drawable[] + { + createCatcherSprite(), + caughtFruit = new Container + { + Anchor = Anchor.TopCentre, + Origin = Anchor.BottomCentre, + } + }; } private int currentDirection; @@ -176,13 +184,13 @@ namespace osu.Game.Rulesets.Catch.UI float distance = fruit.DrawSize.X / 2 * fruit.Scale.X; - while (Children.OfType().Any(f => f.LifetimeEnd == double.PositiveInfinity && Vector2Extensions.DistanceSquared(f.Position, fruit.Position) < distance * distance)) + while (caughtFruit.Any(f => f.LifetimeEnd == double.PositiveInfinity && Vector2Extensions.DistanceSquared(f.Position, fruit.Position) < distance * distance)) { fruit.X += RNG.Next(-5, 5); fruit.Y -= RNG.Next(0, 5); } - Add(fruit); + caughtFruit.Add(fruit); if (((CatchBaseHit)fruit.HitObject).LastInCombo) explode(); @@ -190,29 +198,31 @@ namespace osu.Game.Rulesets.Catch.UI private void explode() { - foreach (var existingFruit in Children.OfType().ToArray()) + var fruit = caughtFruit.ToArray(); + caughtFruit.Clear(false); + + foreach (var f in fruit) { - var originalX = existingFruit.X * Scale.X; + var originalX = f.X * Scale.X; if (ExplodingFruitTarget != null) { - existingFruit.Anchor = Anchor.TopLeft; - existingFruit.Position = ToSpaceOfOtherDrawable(existingFruit.DrawPosition, ExplodingFruitTarget); + f.Anchor = Anchor.TopLeft; + f.Position = ToSpaceOfOtherDrawable(f.DrawPosition, ExplodingFruitTarget); - Remove(existingFruit); + caughtFruit.Remove(f); - ExplodingFruitTarget.Add(existingFruit); + ExplodingFruitTarget.Add(f); } - existingFruit - .MoveToY(existingFruit.Y - 50, 250, Easing.OutSine) - .Then() - .MoveToY(existingFruit.Y + 50, 500, Easing.InSine); + f.MoveToY(f.Y - 50, 250, Easing.OutSine) + .Then() + .MoveToY(f.Y + 50, 500, Easing.InSine); - existingFruit.MoveToX(existingFruit.X + originalX * 6, 1000); - existingFruit.FadeOut(750); + f.MoveToX(f.X + originalX * 6, 1000); + f.FadeOut(750); - existingFruit.Expire(); + f.Expire(); } } } From d3c58c848deba41d97cb71fbce36b4d89a515555 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 18 Sep 2017 12:48:33 +0900 Subject: [PATCH 07/24] Add licence header --- osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs index b5e709885b..6eda627441 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs @@ -1,4 +1,7 @@ -using osu.Game.Beatmaps; +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Beatmaps; using osu.Game.Rulesets.Beatmaps; using osu.Game.Rulesets.Catch.Objects; From 60b38b27764bc1de1a6033c86124146b075b533d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 18 Sep 2017 12:48:45 +0900 Subject: [PATCH 08/24] Add the most basic score calculation for catch --- .../Scoring/CatchScoreProcessor.cs | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs b/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs index 11e95622ca..16756e65f1 100644 --- a/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs +++ b/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs @@ -1,7 +1,10 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Catch.Judgements; using osu.Game.Rulesets.Catch.Objects; +using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; @@ -9,13 +12,22 @@ namespace osu.Game.Rulesets.Catch.Scoring { internal class CatchScoreProcessor : ScoreProcessor { - public CatchScoreProcessor() - { - } - public CatchScoreProcessor(RulesetContainer rulesetContainer) : base(rulesetContainer) { } + + protected override void SimulateAutoplay(Beatmap beatmap) + { + foreach (var obj in beatmap.HitObjects) + { + var fruit = obj as Fruit; + + if (fruit != null) + AddJudgement(new CatchJudgement { Result = HitResult.Perfect }); + } + + base.SimulateAutoplay(beatmap); + } } } From c0c910d4d46eecc65a29c4c6868cd30c7008b0fa Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 19 Sep 2017 15:33:15 +0900 Subject: [PATCH 09/24] Update framework --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index e4101103d7..8e161e9848 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit e4101103d744edc3c8c2abd4a715962bc2fb064e +Subproject commit 8e161e9848996cabf3f779f7d2a18dd615e9d210 From f2a9e95d56d9e776a821ee9d532fa2b88ae94d63 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 19 Sep 2017 17:19:37 +0900 Subject: [PATCH 10/24] Fix type resolution in RulesetStore --- osu.Game/Rulesets/RulesetStore.cs | 121 ++++++++++++++++-------------- 1 file changed, 63 insertions(+), 58 deletions(-) diff --git a/osu.Game/Rulesets/RulesetStore.cs b/osu.Game/Rulesets/RulesetStore.cs index 8d66ad8985..2d271e3592 100644 --- a/osu.Game/Rulesets/RulesetStore.cs +++ b/osu.Game/Rulesets/RulesetStore.cs @@ -17,7 +17,7 @@ namespace osu.Game.Rulesets /// public class RulesetStore : DatabaseBackedStore { - private readonly List instances = new List(); + private static readonly Dictionary loaded_assemblies = new Dictionary(); public IEnumerable AllRulesets => Query().Where(r => r.Available); @@ -25,18 +25,9 @@ namespace osu.Game.Rulesets { } - private const string ruleset_library_prefix = "osu.Game.Rulesets"; - - protected override void Prepare(bool reset = false) + static RulesetStore() { - instances.Clear(); - - Connection.CreateTable(); - - if (reset) - { - Connection.DeleteAll(); - } + AppDomain.CurrentDomain.AssemblyResolve += currentDomain_AssemblyResolve; // todo: don't do this on deploy var sln = DebugUtils.GetSolutionPath(); @@ -50,61 +41,75 @@ namespace osu.Game.Rulesets foreach (string file in Directory.GetFiles(Environment.CurrentDirectory, $"{ruleset_library_prefix}.*.dll")) loadRulesetFromFile(file); - - Connection.BeginTransaction(); - - //add all legacy modes in correct order - foreach (var r in instances.Where(r => r.LegacyID >= 0).OrderBy(r => r.LegacyID)) - { - Connection.InsertOrReplace(createRulesetInfo(r)); - } - - //add any other modes - foreach (var r in instances.Where(r => r.LegacyID < 0)) - { - var us = createRulesetInfo(r); - - var existing = Query().Where(ri => ri.InstantiationInfo == us.InstantiationInfo).FirstOrDefault(); - - if (existing == null) - Connection.Insert(us); - } - - //perform a consistency check - foreach (var r in Query()) - { - try - { - r.CreateInstance(); - r.Available = true; - } - catch - { - r.Available = false; - } - - Connection.Update(r); - } - - Connection.Commit(); } - private void loadRulesetFromFile(string file) + private static Assembly currentDomain_AssemblyResolve(object sender, ResolveEventArgs args) => loaded_assemblies.Keys.FirstOrDefault(a => a.FullName == args.Name); + + private const string ruleset_library_prefix = "osu.Game.Rulesets"; + + protected override void Prepare(bool reset = false) + { + + Connection.CreateTable(); + + if (reset) + { + Connection.DeleteAll(); + } + + var instances = loaded_assemblies.Values.Select(r => (Ruleset)Activator.CreateInstance(r, new RulesetInfo())); + + Connection.RunInTransaction(() => + { + //add all legacy modes in correct order + foreach (var r in instances.Where(r => r.LegacyID >= 0).OrderBy(r => r.LegacyID)) + { + Connection.InsertOrReplace(createRulesetInfo(r)); + } + + //add any other modes + foreach (var r in instances.Where(r => r.LegacyID < 0)) + { + var us = createRulesetInfo(r); + + var existing = Query().Where(ri => ri.InstantiationInfo == us.InstantiationInfo).FirstOrDefault(); + + if (existing == null) + Connection.Insert(us); + } + }); + + Connection.RunInTransaction(() => + { + //perform a consistency check + foreach (var r in Query()) + { + try + { + r.CreateInstance(); + r.Available = true; + } + catch + { + r.Available = false; + } + + Connection.Update(r); + } + }); + } + + private static void loadRulesetFromFile(string file) { var filename = Path.GetFileNameWithoutExtension(file); - if (instances.Any(i => i.GetType().Namespace == filename)) + if (loaded_assemblies.Values.Any(t => t.Namespace == filename)) return; try { - var assembly = Assembly.LoadFile(file); - var rulesets = assembly.GetTypes().Where(t => t.IsSubclassOf(typeof(Ruleset))); - - if (rulesets.Count() != 1) - return; - - instances.Add((Ruleset)Activator.CreateInstance(rulesets.First(), new RulesetInfo())); + var assembly = Assembly.LoadFrom(file); + loaded_assemblies[assembly] = assembly.GetTypes().First(t => t.IsSubclassOf(typeof(Ruleset))); } catch (Exception) { } } From 51cdff1d9aa0f8def3322afde4d49d8e687b23b4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 19 Sep 2017 17:22:45 +0900 Subject: [PATCH 11/24] Fix TestCasePlaySongSelect incorrectly using live app data --- .../Tests/Visual/TestCasePlaySongSelect.cs | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/osu.Game/Tests/Visual/TestCasePlaySongSelect.cs b/osu.Game/Tests/Visual/TestCasePlaySongSelect.cs index 363038e2fd..feff7497d8 100644 --- a/osu.Game/Tests/Visual/TestCasePlaySongSelect.cs +++ b/osu.Game/Tests/Visual/TestCasePlaySongSelect.cs @@ -2,9 +2,11 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; +using osu.Framework.Allocation; using osu.Framework.MathUtils; using osu.Game.Beatmaps; using osu.Game.Database; +using osu.Game.IO; using osu.Game.Rulesets; using osu.Game.Screens.Select; using osu.Game.Screens.Select.Filter; @@ -14,13 +16,20 @@ namespace osu.Game.Tests.Visual { internal class TestCasePlaySongSelect : OsuTestCase { - private readonly BeatmapManager manager; + private BeatmapManager manager; public override string Description => @"with fake data"; - private readonly RulesetStore rulesets; + private RulesetStore rulesets; - public TestCasePlaySongSelect() + private DependencyContainer dependencies; + + private FileStore files; + + protected override IReadOnlyDependencyContainer CreateLocalDependencies(IReadOnlyDependencyContainer parent) => dependencies = new DependencyContainer(parent); + + [BackgroundDependencyLoader] + private void load() { PlaySongSelect songSelect; @@ -31,8 +40,9 @@ namespace osu.Game.Tests.Visual var backingDatabase = storage.GetDatabase(@"client"); backingDatabase.CreateTable(); - rulesets = new RulesetStore(backingDatabase); - manager = new BeatmapManager(storage, null, backingDatabase, rulesets, null); + dependencies.Cache(rulesets = new RulesetStore(backingDatabase)); + dependencies.Cache(files = new FileStore(backingDatabase, storage)); + dependencies.Cache(manager = new BeatmapManager(storage, files, backingDatabase, rulesets, null)); for (int i = 0; i < 100; i += 10) manager.Import(createTestBeatmapSet(i)); From c41ca10715d2d1b5b3dd2c71f291c3562d8e39c9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 19 Sep 2017 18:34:58 +0900 Subject: [PATCH 12/24] Allow files missing on disk to be restored on beatmap import Previously, in the rare case the database became out of sync with the disk store, it was impossible to feasibly repair a beatmap. Now reimporting checks each file exists on disk and adds it back if it doesn't. --- osu.Game/Beatmaps/BeatmapManager.cs | 9 ++++++++ osu.Game/IO/FileStore.cs | 32 ++++++++++++++--------------- 2 files changed, 25 insertions(+), 16 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index f58b3505c5..a1b678392b 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -429,6 +429,15 @@ namespace osu.Game.Beatmaps if (beatmapSet != null) { Undelete(beatmapSet); + + // ensure all files are present and accessible + foreach (var f in beatmapSet.Files) + { + if (!storage.Exists(f.FileInfo.StoragePath)) + using (Stream s = reader.GetStream(f.Filename)) + files.Add(s, false); + } + return beatmapSet; } diff --git a/osu.Game/IO/FileStore.cs b/osu.Game/IO/FileStore.cs index 1011fa3236..c3d8c1df46 100644 --- a/osu.Game/IO/FileStore.cs +++ b/osu.Game/IO/FileStore.cs @@ -78,33 +78,33 @@ namespace osu.Game.IO } } - public FileInfo Add(Stream data) + public FileInfo Add(Stream data, bool reference = true) { string hash = data.ComputeSHA2Hash(); var existing = Connection.Table().Where(f => f.Hash == hash).FirstOrDefault(); var info = existing ?? new FileInfo { Hash = hash }; - if (existing != null) + + string path = Path.Combine(prefix, info.StoragePath); + + // we may be re-adding a file to fix missing store entries. + if (!Storage.Exists(path)) { - info = existing; + data.Seek(0, SeekOrigin.Begin); + + using (var output = Storage.GetStream(path, FileAccess.Write)) + data.CopyTo(output); + + data.Seek(0, SeekOrigin.Begin); } - else - { - string path = Path.Combine(prefix, info.StoragePath); - - data.Seek(0, SeekOrigin.Begin); - - if (!Storage.Exists(path)) - using (var output = Storage.GetStream(path, FileAccess.Write)) - data.CopyTo(output); - - data.Seek(0, SeekOrigin.Begin); + if (existing == null) Connection.Insert(info); - } - Reference(info); + if (reference || existing == null) + Reference(info); + return info; } From 99b512cce57d2308cde8dea7ffbfe6ba84cbb32e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 19 Sep 2017 19:27:14 +0900 Subject: [PATCH 13/24] Output ruleset assemblies to the game folder rather than adding special logic --- .../osu.Game.Rulesets.Catch.csproj | 2 +- .../osu.Game.Rulesets.Mania.csproj | 2 +- osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj | 2 +- .../osu.Game.Rulesets.Taiko.csproj | 2 +- osu.Game/Rulesets/RulesetStore.cs | 11 ----------- 5 files changed, 4 insertions(+), 15 deletions(-) diff --git a/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj index 639e9135c8..4ef60cd80e 100644 --- a/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj +++ b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj @@ -16,7 +16,7 @@ true full false - bin\Debug\ + ..\osu.Game\bin\Debug\ DEBUG;TRACE prompt 4 diff --git a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj index 6d0e56cb0c..48a028184d 100644 --- a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj +++ b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj @@ -16,7 +16,7 @@ true full false - bin\Debug\ + ..\osu.Game\bin\Debug\ DEBUG;TRACE prompt 4 diff --git a/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj b/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj index 338a2b9045..dd13faf2ef 100644 --- a/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj +++ b/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj @@ -17,7 +17,7 @@ true full false - bin\Debug\ + ..\osu.Game\bin\Debug\ DEBUG;TRACE prompt 4 diff --git a/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj b/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj index d38b24f933..598602a6e8 100644 --- a/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj +++ b/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj @@ -16,7 +16,7 @@ true full false - bin\Debug\ + ..\osu.Game\bin\Debug\ DEBUG;TRACE prompt 4 diff --git a/osu.Game/Rulesets/RulesetStore.cs b/osu.Game/Rulesets/RulesetStore.cs index 2d271e3592..5eef4a8470 100644 --- a/osu.Game/Rulesets/RulesetStore.cs +++ b/osu.Game/Rulesets/RulesetStore.cs @@ -6,7 +6,6 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; -using osu.Framework.Development; using osu.Game.Database; using SQLite.Net; @@ -29,16 +28,6 @@ namespace osu.Game.Rulesets { AppDomain.CurrentDomain.AssemblyResolve += currentDomain_AssemblyResolve; - // todo: don't do this on deploy - var sln = DebugUtils.GetSolutionPath(); - - if (sln != null) - { - foreach (string dir in Directory.GetDirectories(sln, $"{ruleset_library_prefix}.*")) - foreach (string file in Directory.GetFiles(Path.Combine(dir, "bin", DebugUtils.IsDebug ? "Debug" : "Release"), $"{ruleset_library_prefix}.*.dll")) - loadRulesetFromFile(file); - } - foreach (string file in Directory.GetFiles(Environment.CurrentDirectory, $"{ruleset_library_prefix}.*.dll")) loadRulesetFromFile(file); } From 390c212dcbc8a6960117bdb5ab78086571a358c0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 19 Sep 2017 20:04:13 +0900 Subject: [PATCH 14/24] Don't die on a null connection during disposal May be caused by a startup error. This shouldn't result in an additional exception here. --- osu.Game/OsuGameBase.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 9f831b58fb..448dccdd72 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -231,7 +231,7 @@ namespace osu.Game LocalConfig.Save(); } - connection.Dispose(); + connection?.Dispose(); base.Dispose(isDisposing); } From ef210018d9bca50a640cbcfbbf805ff78f7284b8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 19 Sep 2017 20:04:37 +0900 Subject: [PATCH 15/24] Run headless tests with a unique name based on the executing assembly --- osu.Game/Tests/Visual/OsuTestCase.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Tests/Visual/OsuTestCase.cs b/osu.Game/Tests/Visual/OsuTestCase.cs index 8b272f01a4..d722f7d711 100644 --- a/osu.Game/Tests/Visual/OsuTestCase.cs +++ b/osu.Game/Tests/Visual/OsuTestCase.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; using osu.Framework.Platform; using osu.Framework.Testing; @@ -10,7 +11,7 @@ namespace osu.Game.Tests.Visual { public override void RunTest() { - using (var host = new HeadlessGameHost(realtime: false)) + using (var host = new HeadlessGameHost(AppDomain.CurrentDomain.FriendlyName.Replace(' ', '-'), realtime: false)) host.Run(new OsuTestCaseTestRunner(this)); } From 05303d37d307f9a1d62da00ccff0cc3fab53fdc8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 19 Sep 2017 20:43:29 +0900 Subject: [PATCH 16/24] Update framework --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index 8e161e9848..e1352a8b0b 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 8e161e9848996cabf3f779f7d2a18dd615e9d210 +Subproject commit e1352a8b0b5d1ba8acd9335a56c714d2ccc2f6a6 From c88b0784dae4dc40a559c297a496a09ecaef8920 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 19 Sep 2017 21:39:17 +0900 Subject: [PATCH 17/24] Use MaxValue instead of PositiveInfinity --- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index dad9cd2715..41b76c8c0d 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -184,7 +184,7 @@ namespace osu.Game.Rulesets.Catch.UI float distance = fruit.DrawSize.X / 2 * fruit.Scale.X; - while (caughtFruit.Any(f => f.LifetimeEnd == double.PositiveInfinity && Vector2Extensions.DistanceSquared(f.Position, fruit.Position) < distance * distance)) + while (caughtFruit.Any(f => f.LifetimeEnd == double.MaxValue && Vector2Extensions.DistanceSquared(f.Position, fruit.Position) < distance * distance)) { fruit.X += RNG.Next(-5, 5); fruit.Y -= RNG.Next(0, 5); From 4b68950428d32311d398597f23b730bca6397d34 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 19 Sep 2017 21:39:53 +0900 Subject: [PATCH 18/24] Fix incorrect coordinate mapping on fruit explosion --- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 41b76c8c0d..a4f31fc8e4 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -199,7 +199,6 @@ namespace osu.Game.Rulesets.Catch.UI private void explode() { var fruit = caughtFruit.ToArray(); - caughtFruit.Clear(false); foreach (var f in fruit) { @@ -208,7 +207,7 @@ namespace osu.Game.Rulesets.Catch.UI if (ExplodingFruitTarget != null) { f.Anchor = Anchor.TopLeft; - f.Position = ToSpaceOfOtherDrawable(f.DrawPosition, ExplodingFruitTarget); + f.Position = caughtFruit.ToSpaceOfOtherDrawable(f.DrawPosition, ExplodingFruitTarget); caughtFruit.Remove(f); From 0aa152974acebb73ff68f7838dfa82f0fde4fe57 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 19 Sep 2017 21:40:38 +0900 Subject: [PATCH 19/24] Add interfaces to CatchBaseHit --- osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs | 2 +- osu.Game.Rulesets.Catch/Objects/CatchBaseHit.cs | 5 +++-- osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs | 2 +- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 2 +- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs index bc6313b2ac..2efb0c0707 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs @@ -24,7 +24,7 @@ namespace osu.Game.Rulesets.Catch.Beatmaps { StartTime = obj.StartTime, NewCombo = (obj as IHasCombo)?.NewCombo ?? false, - Position = ((IHasXPosition)obj).X / OsuPlayfield.BASE_SIZE.X + X = ((IHasXPosition)obj).X / OsuPlayfield.BASE_SIZE.X }; } } diff --git a/osu.Game.Rulesets.Catch/Objects/CatchBaseHit.cs b/osu.Game.Rulesets.Catch/Objects/CatchBaseHit.cs index 42b50a3867..2f33cf1093 100644 --- a/osu.Game.Rulesets.Catch/Objects/CatchBaseHit.cs +++ b/osu.Game.Rulesets.Catch/Objects/CatchBaseHit.cs @@ -2,13 +2,14 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Objects.Types; using OpenTK.Graphics; namespace osu.Game.Rulesets.Catch.Objects { - public abstract class CatchBaseHit : HitObject + public abstract class CatchBaseHit : HitObject, IHasXPosition, IHasCombo { - public float Position { get; set; } + public float X { get; set; } public Color4 ComboColour { get; set; } = Color4.Gray; public int ComboIndex { get; set; } diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs index 9d07c9d8dd..e0c9f0c028 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs @@ -56,7 +56,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable Size = new Vector2(pulp_size * 2.2f, pulp_size * 2.8f); RelativePositionAxes = Axes.Both; - X = h.Position; + X = h.X; AccentColour = HitObject.ComboColour; diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index a4f31fc8e4..2930dbb7cc 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.Catch.UI public void Add(DrawableHitObject fruit, Vector2 screenPosition) => catcher.AddToStack(fruit, screenPosition); - public bool CheckIfWeCanCatch(CatchBaseHit obj) => Math.Abs(catcher.Position.X - obj.Position) < catcher.DrawSize.X / DrawSize.X / 2; + public bool CheckIfWeCanCatch(CatchBaseHit obj) => Math.Abs(catcher.Position.X - obj.X) < catcher.DrawSize.X / DrawSize.X / 2; [BackgroundDependencyLoader] private void load() From f96875a470e53cdd0480b84ea3ca724887cbc6a5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 19 Sep 2017 21:40:57 +0900 Subject: [PATCH 20/24] Add a catch specific player test --- .../Tests/TestCaseCatchPlayer.cs | 20 +++++++++++++++++++ .../osu.Game.Rulesets.Catch.csproj | 1 + osu.Game/Tests/Visual/TestCasePlayer.cs | 11 ++++++++-- 3 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 osu.Game.Rulesets.Catch/Tests/TestCaseCatchPlayer.cs diff --git a/osu.Game.Rulesets.Catch/Tests/TestCaseCatchPlayer.cs b/osu.Game.Rulesets.Catch/Tests/TestCaseCatchPlayer.cs new file mode 100644 index 0000000000..55e6d8d226 --- /dev/null +++ b/osu.Game.Rulesets.Catch/Tests/TestCaseCatchPlayer.cs @@ -0,0 +1,20 @@ +using NUnit.Framework; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Catch.Objects; + +namespace osu.Game.Rulesets.Catch.Tests +{ + [TestFixture] + public class TestCaseCatchPlayer : Game.Tests.Visual.TestCasePlayer + { + protected override Beatmap CreateBeatmap() + { + var beatmap = new Beatmap(); + + for (int i = 0; i < 256; i++) + beatmap.HitObjects.Add(new Fruit { X = 0.5f, StartTime = i * 100, NewCombo = i % 8 == 0 }); + + return beatmap; + } + } +} diff --git a/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj index 43124e4146..323a934e27 100644 --- a/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj +++ b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj @@ -58,6 +58,7 @@ + diff --git a/osu.Game/Tests/Visual/TestCasePlayer.cs b/osu.Game/Tests/Visual/TestCasePlayer.cs index 49146c4173..4a25a52e36 100644 --- a/osu.Game/Tests/Visual/TestCasePlayer.cs +++ b/osu.Game/Tests/Visual/TestCasePlayer.cs @@ -16,7 +16,7 @@ using OpenTK.Graphics; namespace osu.Game.Tests.Visual { - internal class TestCasePlayer : OsuTestCase + public class TestCasePlayer : OsuTestCase { protected Player Player; private RulesetStore rulesets; @@ -45,7 +45,7 @@ namespace osu.Game.Tests.Visual loadPlayerFor(rulesets.Query().First()); } - private void loadPlayerFor(RulesetInfo r) + protected virtual Beatmap CreateBeatmap() { Beatmap beatmap; @@ -53,6 +53,13 @@ namespace osu.Game.Tests.Visual using (var reader = new StreamReader(stream)) beatmap = BeatmapDecoder.GetDecoder(reader).Decode(reader); + return beatmap; + } + + private void loadPlayerFor(RulesetInfo r) + { + var beatmap = CreateBeatmap(); + beatmap.BeatmapInfo.Ruleset = r; var instance = r.CreateInstance(); From 3000323727760a3141e6a0065374d212452702b8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 19 Sep 2017 21:41:18 +0900 Subject: [PATCH 21/24] Give WorkingBeatmap's Metadata a non-null default --- osu.Game/Beatmaps/WorkingBeatmap.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index bb3122489e..277846ee80 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -25,7 +25,7 @@ namespace osu.Game.Beatmaps { BeatmapInfo = beatmapInfo; BeatmapSetInfo = beatmapInfo.BeatmapSet; - Metadata = beatmapInfo.Metadata ?? BeatmapSetInfo.Metadata; + Metadata = beatmapInfo.Metadata ?? BeatmapSetInfo?.Metadata ?? new BeatmapMetadata(); Mods.ValueChanged += mods => applyRateAdjustments(); } From 611f4df484972eb8236c2b3fd7ed12faf67d9d14 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 19 Sep 2017 21:41:51 +0900 Subject: [PATCH 22/24] Add licence header --- osu.Game.Rulesets.Catch/Tests/TestCaseCatchPlayer.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/Tests/TestCaseCatchPlayer.cs b/osu.Game.Rulesets.Catch/Tests/TestCaseCatchPlayer.cs index 55e6d8d226..8d18a712d8 100644 --- a/osu.Game.Rulesets.Catch/Tests/TestCaseCatchPlayer.cs +++ b/osu.Game.Rulesets.Catch/Tests/TestCaseCatchPlayer.cs @@ -1,4 +1,7 @@ -using NUnit.Framework; +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using NUnit.Framework; using osu.Game.Beatmaps; using osu.Game.Rulesets.Catch.Objects; From e0911f014e076701a693224a4904dcbee668bba7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 19 Sep 2017 22:50:28 +0900 Subject: [PATCH 23/24] Fix ruleset target path for release builds --- osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj | 2 +- osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj | 2 +- osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj | 2 +- osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj index 323a934e27..787825d482 100644 --- a/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj +++ b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj @@ -26,7 +26,7 @@ pdbonly true - bin\Release\ + ..\osu.Game\bin\Release\ TRACE prompt 4 diff --git a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj index 48a028184d..fa8b9d35aa 100644 --- a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj +++ b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj @@ -26,7 +26,7 @@ pdbonly true - bin\Release\ + ..\osu.Game\bin\Release\ TRACE prompt 4 diff --git a/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj b/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj index dd13faf2ef..300000754c 100644 --- a/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj +++ b/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj @@ -27,7 +27,7 @@ pdbonly true - bin\Release\ + ..\osu.Game\bin\Release\ TRACE prompt 4 diff --git a/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj b/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj index 598602a6e8..2c49be287b 100644 --- a/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj +++ b/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj @@ -26,7 +26,7 @@ pdbonly true - bin\Release\ + ..\osu.Game\bin\Release\ TRACE prompt 4 From 2923af19461383a71cc86889eeee388a0c85c6cb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 19 Sep 2017 23:35:23 +0900 Subject: [PATCH 24/24] Allow deploy script to deploy multiple project targets --- osu.Desktop.Deploy/Program.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Desktop.Deploy/Program.cs b/osu.Desktop.Deploy/Program.cs index a181a6fa5e..785f915a3e 100644 --- a/osu.Desktop.Deploy/Program.cs +++ b/osu.Desktop.Deploy/Program.cs @@ -29,7 +29,7 @@ namespace osu.Desktop.Deploy public static string SolutionName = ConfigurationManager.AppSettings["SolutionName"]; public static string ProjectName = ConfigurationManager.AppSettings["ProjectName"]; public static string NuSpecName = ConfigurationManager.AppSettings["NuSpecName"]; - public static string TargetName = ConfigurationManager.AppSettings["TargetName"]; + public static string TargetNames = ConfigurationManager.AppSettings["TargetName"]; public static string PackageName = ConfigurationManager.AppSettings["PackageName"]; public static string IconName = ConfigurationManager.AppSettings["IconName"]; public static string CodeSigningCertificate = ConfigurationManager.AppSettings["CodeSigningCertificate"]; @@ -100,7 +100,8 @@ namespace osu.Desktop.Deploy updateAssemblyInfo(version); write("Running build process..."); - runCommand(msbuild_path, $"/v:quiet /m /t:{TargetName.Replace('.', '_')} /p:OutputPath={stagingPath};Targets=\"Clean;Build\";Configuration=Release {SolutionName}.sln"); + foreach (string targetName in TargetNames.Split(',')) + runCommand(msbuild_path, $"/v:quiet /m /t:{targetName.Replace('.', '_')} /p:OutputPath={stagingPath};Targets=\"Clean;Build\";Configuration=Release {SolutionName}.sln"); write("Creating NuGet deployment package..."); runCommand(nuget_path, $"pack {NuSpecName} -Version {version} -Properties Configuration=Deploy -OutputDirectory {stagingPath} -BasePath {stagingPath}");