diff --git a/osu.Android.props b/osu.Android.props
index 0ac766926c..13b4b6ebbb 100644
--- a/osu.Android.props
+++ b/osu.Android.props
@@ -51,7 +51,7 @@
-
+
diff --git a/osu.Game.Rulesets.Catch/Objects/Banana.cs b/osu.Game.Rulesets.Catch/Objects/Banana.cs
index 0b3d1d23e0..4ecfb7b16d 100644
--- a/osu.Game.Rulesets.Catch/Objects/Banana.cs
+++ b/osu.Game.Rulesets.Catch/Objects/Banana.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.Collections.Generic;
+using osu.Game.Audio;
using osu.Game.Rulesets.Catch.Judgements;
using osu.Game.Rulesets.Judgements;
@@ -8,8 +10,27 @@ namespace osu.Game.Rulesets.Catch.Objects
{
public class Banana : Fruit
{
+ ///
+ /// Index of banana in current shower.
+ ///
+ public int BananaIndex;
+
public override FruitVisualRepresentation VisualRepresentation => FruitVisualRepresentation.Banana;
public override Judgement CreateJudgement() => new CatchBananaJudgement();
+
+ private static readonly List samples = new List { new BananaHitSampleInfo() };
+
+ public Banana()
+ {
+ Samples = samples;
+ }
+
+ private class BananaHitSampleInfo : HitSampleInfo
+ {
+ private static string[] lookupNames { get; } = { "metronomelow", "catch-banana" };
+
+ public override IEnumerable LookupNames => lookupNames;
+ }
}
}
diff --git a/osu.Game.Rulesets.Catch/Objects/BananaShower.cs b/osu.Game.Rulesets.Catch/Objects/BananaShower.cs
index 04a995c77e..89c51459a6 100644
--- a/osu.Game.Rulesets.Catch/Objects/BananaShower.cs
+++ b/osu.Game.Rulesets.Catch/Objects/BananaShower.cs
@@ -30,15 +30,21 @@ namespace osu.Game.Rulesets.Catch.Objects
if (spacing <= 0)
return;
- for (double i = StartTime; i <= EndTime; i += spacing)
+ double time = StartTime;
+ int i = 0;
+
+ while (time <= EndTime)
{
cancellationToken.ThrowIfCancellationRequested();
AddNested(new Banana
{
- Samples = Samples,
- StartTime = i
+ StartTime = time,
+ BananaIndex = i,
});
+
+ time += spacing;
+ i++;
}
}
diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableBanana.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableBanana.cs
index 01b76ceed9..a865984d45 100644
--- a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableBanana.cs
+++ b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableBanana.cs
@@ -40,6 +40,13 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables
float getRandomAngle() => 180 * (RNG.NextSingle() * 2 - 1);
}
+ public override void PlaySamples()
+ {
+ base.PlaySamples();
+ if (Samples != null)
+ Samples.Frequency.Value = 0.77f + ((Banana)HitObject).BananaIndex * 0.006f;
+ }
+
private Color4 getBananaColour()
{
switch (RNG.Next(0, 3))
diff --git a/osu.Game/Online/Multiplayer/CreateRoomScoreRequest.cs b/osu.Game/Online/Multiplayer/CreateRoomScoreRequest.cs
index f973f96b37..2d99b12519 100644
--- a/osu.Game/Online/Multiplayer/CreateRoomScoreRequest.cs
+++ b/osu.Game/Online/Multiplayer/CreateRoomScoreRequest.cs
@@ -11,17 +11,20 @@ namespace osu.Game.Online.Multiplayer
{
private readonly int roomId;
private readonly int playlistItemId;
+ private readonly string versionHash;
- public CreateRoomScoreRequest(int roomId, int playlistItemId)
+ public CreateRoomScoreRequest(int roomId, int playlistItemId, string versionHash)
{
this.roomId = roomId;
this.playlistItemId = playlistItemId;
+ this.versionHash = versionHash;
}
protected override WebRequest CreateWebRequest()
{
var req = base.CreateWebRequest();
req.Method = HttpMethod.Post;
+ req.AddParameter("version_hash", versionHash);
return req;
}
diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs
index fe5c0704b7..278f2d849f 100644
--- a/osu.Game/OsuGameBase.cs
+++ b/osu.Game/OsuGameBase.cs
@@ -11,6 +11,7 @@ using osu.Framework.Allocation;
using osu.Framework.Audio;
using osu.Framework.Bindables;
using osu.Framework.Development;
+using osu.Framework.Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.IO.Stores;
@@ -97,6 +98,11 @@ namespace osu.Game
public virtual Version AssemblyVersion => Assembly.GetEntryAssembly()?.GetName().Version ?? new Version();
+ ///
+ /// MD5 representation of the game executable.
+ ///
+ public string VersionHash { get; private set; }
+
public bool IsDeployedBuild => AssemblyVersion.Major > 0;
public virtual string Version
@@ -128,6 +134,9 @@ namespace osu.Game
[BackgroundDependencyLoader]
private void load()
{
+ using (var str = File.OpenRead(typeof(OsuGameBase).Assembly.Location))
+ VersionHash = str.ComputeMD5Hash();
+
Resources.AddStore(new DllResourceStore(OsuResources.ResourceAssembly));
dependencies.Cache(contextFactory = new DatabaseContextFactory(Storage));
diff --git a/osu.Game/Rulesets/RulesetStore.cs b/osu.Game/Rulesets/RulesetStore.cs
index 58a2ba056e..dd43092c0d 100644
--- a/osu.Game/Rulesets/RulesetStore.cs
+++ b/osu.Game/Rulesets/RulesetStore.cs
@@ -65,11 +65,15 @@ namespace osu.Game.Rulesets
// the requesting assembly may be located out of the executable's base directory, thus requiring manual resolving of its dependencies.
// this attempts resolving the ruleset dependencies on game core and framework assemblies by returning assemblies with the same assembly name
// already loaded in the AppDomain.
- foreach (var curAsm in AppDomain.CurrentDomain.GetAssemblies())
- {
- if (asm.Name.Equals(curAsm.GetName().Name, StringComparison.Ordinal))
- return curAsm;
- }
+ var domainAssembly = AppDomain.CurrentDomain.GetAssemblies()
+ // Given name is always going to be equally-or-more qualified than the assembly name.
+ .Where(a => args.Name.Contains(a.GetName().Name, StringComparison.Ordinal))
+ // Pick the greatest assembly version.
+ .OrderByDescending(a => a.GetName().Version)
+ .FirstOrDefault();
+
+ if (domainAssembly != null)
+ return domainAssembly;
return loadedAssemblies.Keys.FirstOrDefault(a => a.FullName == asm.FullName);
}
diff --git a/osu.Game/Screens/Multi/Play/TimeshiftPlayer.cs b/osu.Game/Screens/Multi/Play/TimeshiftPlayer.cs
index c2381fe219..da082692d7 100644
--- a/osu.Game/Screens/Multi/Play/TimeshiftPlayer.cs
+++ b/osu.Game/Screens/Multi/Play/TimeshiftPlayer.cs
@@ -58,7 +58,7 @@ namespace osu.Game.Screens.Multi.Play
if (!playlistItem.RequiredMods.All(m => Mods.Value.Any(m.Equals)))
throw new InvalidOperationException("Current Mods do not match PlaylistItem's RequiredMods");
- var req = new CreateRoomScoreRequest(roomId.Value ?? 0, playlistItem.ID);
+ var req = new CreateRoomScoreRequest(roomId.Value ?? 0, playlistItem.ID, Game.VersionHash);
req.Success += r => token = r.ID;
req.Failure += e =>
{
diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj
index 1ececa448c..745555e0e2 100644
--- a/osu.Game/osu.Game.csproj
+++ b/osu.Game/osu.Game.csproj
@@ -25,7 +25,7 @@
-
+
diff --git a/osu.iOS.props b/osu.iOS.props
index ef5ba10d17..f1080f0c8b 100644
--- a/osu.iOS.props
+++ b/osu.iOS.props
@@ -71,7 +71,7 @@
-
+