diff --git a/Osu.Patcher.Hook/Patches/BeatmapMirror/EnableOsuDirect.cs b/Osu.Patcher.Hook/Patches/BeatmapMirror/EnableOsuDirect.cs
index 9e3c251..6bc73a2 100644
--- a/Osu.Patcher.Hook/Patches/BeatmapMirror/EnableOsuDirect.cs
+++ b/Osu.Patcher.Hook/Patches/BeatmapMirror/EnableOsuDirect.cs
@@ -2,7 +2,6 @@
using System.Reflection;
using HarmonyLib;
using JetBrains.Annotations;
-using Osu.Stubs;
using Osu.Stubs.Other;
using Osu.Utils.Extensions;
using static System.Reflection.Emit.OpCodes;
diff --git a/Osu.Patcher.Hook/Patches/LivePerformance/AddPerformanceToUi.cs b/Osu.Patcher.Hook/Patches/LivePerformance/AddPerformanceToUi.cs
index c00d71a..478a0e7 100644
--- a/Osu.Patcher.Hook/Patches/LivePerformance/AddPerformanceToUi.cs
+++ b/Osu.Patcher.Hook/Patches/LivePerformance/AddPerformanceToUi.cs
@@ -4,7 +4,6 @@
using System.Reflection;
using HarmonyLib;
using JetBrains.Annotations;
-using Osu.Stubs;
using Osu.Stubs.Framework;
using Osu.Stubs.GameModes;
using Osu.Stubs.Graphics;
diff --git a/Osu.Patcher.Hook/Patches/LivePerformance/PerformanceCalculator.cs b/Osu.Patcher.Hook/Patches/LivePerformance/PerformanceCalculator.cs
index 24e9597..97d1c61 100644
--- a/Osu.Patcher.Hook/Patches/LivePerformance/PerformanceCalculator.cs
+++ b/Osu.Patcher.Hook/Patches/LivePerformance/PerformanceCalculator.cs
@@ -1,7 +1,6 @@
using System;
using System.Diagnostics;
using Osu.Performance;
-using Osu.Stubs;
using Osu.Stubs.GameModes;
using Osu.Stubs.Other;
using Osu.Stubs.Scoring;
diff --git a/Osu.Patcher.Hook/Patches/LivePerformance/PerformanceDisplay.cs b/Osu.Patcher.Hook/Patches/LivePerformance/PerformanceDisplay.cs
index 96ebb0f..0306061 100644
--- a/Osu.Patcher.Hook/Patches/LivePerformance/PerformanceDisplay.cs
+++ b/Osu.Patcher.Hook/Patches/LivePerformance/PerformanceDisplay.cs
@@ -1,5 +1,4 @@
using System;
-using Osu.Stubs;
using Osu.Stubs.Framework;
namespace Osu.Patcher.Hook.Patches.LivePerformance;
diff --git a/Osu.Patcher.Hook/Patches/LivePerformance/TrackOnScoreHit.cs b/Osu.Patcher.Hook/Patches/LivePerformance/TrackOnScoreHit.cs
index 75b9fa2..eed9ded 100644
--- a/Osu.Patcher.Hook/Patches/LivePerformance/TrackOnScoreHit.cs
+++ b/Osu.Patcher.Hook/Patches/LivePerformance/TrackOnScoreHit.cs
@@ -5,7 +5,6 @@
using HarmonyLib;
using JetBrains.Annotations;
using Osu.Performance;
-using Osu.Stubs;
using Osu.Stubs.Rulesets;
using Osu.Stubs.Scoring;
diff --git a/Osu.Patcher.Hook/Patches/LivePerformance/TrackResetScore.cs b/Osu.Patcher.Hook/Patches/LivePerformance/TrackResetScore.cs
index 6b86fa7..97543f1 100644
--- a/Osu.Patcher.Hook/Patches/LivePerformance/TrackResetScore.cs
+++ b/Osu.Patcher.Hook/Patches/LivePerformance/TrackResetScore.cs
@@ -1,7 +1,6 @@
using System.Reflection;
using HarmonyLib;
using JetBrains.Annotations;
-using Osu.Stubs;
using Osu.Stubs.Rulesets;
namespace Osu.Patcher.Hook.Patches.LivePerformance;
diff --git a/Osu.Patcher.Hook/Patches/Misc/AllowPlayModeReload.cs b/Osu.Patcher.Hook/Patches/Misc/AllowPlayModeReload.cs
index 5e312a4..cf632ff 100644
--- a/Osu.Patcher.Hook/Patches/Misc/AllowPlayModeReload.cs
+++ b/Osu.Patcher.Hook/Patches/Misc/AllowPlayModeReload.cs
@@ -3,7 +3,6 @@
using HarmonyLib;
using JetBrains.Annotations;
using Osu.Patcher.Hook.Patches.UI;
-using Osu.Stubs;
using Osu.Stubs.Other;
using Osu.Utils.Extensions;
using static System.Reflection.Emit.OpCodes;
diff --git a/Osu.Patcher.Hook/Patches/Misc/DisableErrorReporting.cs b/Osu.Patcher.Hook/Patches/Misc/DisableErrorReporting.cs
index 6b9206e..86ef251 100644
--- a/Osu.Patcher.Hook/Patches/Misc/DisableErrorReporting.cs
+++ b/Osu.Patcher.Hook/Patches/Misc/DisableErrorReporting.cs
@@ -1,7 +1,6 @@
using System.Reflection;
using HarmonyLib;
using JetBrains.Annotations;
-using Osu.Stubs;
using Osu.Stubs.Helpers;
namespace Osu.Patcher.Hook.Patches.Misc;
diff --git a/Osu.Patcher.Hook/Patches/Misc/FixDoubleSkipping.cs b/Osu.Patcher.Hook/Patches/Misc/FixDoubleSkipping.cs
index a7766e7..312a6c9 100644
--- a/Osu.Patcher.Hook/Patches/Misc/FixDoubleSkipping.cs
+++ b/Osu.Patcher.Hook/Patches/Misc/FixDoubleSkipping.cs
@@ -3,7 +3,6 @@
using System.Reflection;
using HarmonyLib;
using JetBrains.Annotations;
-using Osu.Stubs;
using Osu.Stubs.GameModes;
using Osu.Stubs.Other;
diff --git a/Osu.Patcher.Hook/Patches/Misc/LogOsuLogger.cs b/Osu.Patcher.Hook/Patches/Misc/LogOsuLogger.cs
index dec58ec..a6c2fe3 100644
--- a/Osu.Patcher.Hook/Patches/Misc/LogOsuLogger.cs
+++ b/Osu.Patcher.Hook/Patches/Misc/LogOsuLogger.cs
@@ -5,7 +5,6 @@
using System.Reflection;
using HarmonyLib;
using JetBrains.Annotations;
-using Osu.Stubs;
using Osu.Stubs.Helpers;
namespace Osu.Patcher.Hook.Patches.Misc;
diff --git a/Osu.Patcher.Hook/Patches/Misc/LogSoftErrors.cs b/Osu.Patcher.Hook/Patches/Misc/LogSoftErrors.cs
index 5b06b88..918f8ec 100644
--- a/Osu.Patcher.Hook/Patches/Misc/LogSoftErrors.cs
+++ b/Osu.Patcher.Hook/Patches/Misc/LogSoftErrors.cs
@@ -2,7 +2,6 @@
using System.Reflection;
using HarmonyLib;
using JetBrains.Annotations;
-using Osu.Stubs;
using Osu.Stubs.Other;
namespace Osu.Patcher.Hook.Patches.Misc;
diff --git a/Osu.Patcher.Hook/Patches/Mods/PatchSuddenDeathAutoRetry.cs b/Osu.Patcher.Hook/Patches/Mods/PatchSuddenDeathAutoRetry.cs
index f3eb5ff..bf0b27e 100644
--- a/Osu.Patcher.Hook/Patches/Mods/PatchSuddenDeathAutoRetry.cs
+++ b/Osu.Patcher.Hook/Patches/Mods/PatchSuddenDeathAutoRetry.cs
@@ -2,7 +2,6 @@
using System.Reflection;
using HarmonyLib;
using JetBrains.Annotations;
-using Osu.Stubs;
using Osu.Stubs.Rulesets;
using static System.Reflection.Emit.OpCodes;
diff --git a/Osu.Patcher.Hook/Patches/UI/AllowOpenOptionsInGameplay.cs b/Osu.Patcher.Hook/Patches/UI/AllowOpenOptionsInGameplay.cs
index 4d5d224..124b814 100644
--- a/Osu.Patcher.Hook/Patches/UI/AllowOpenOptionsInGameplay.cs
+++ b/Osu.Patcher.Hook/Patches/UI/AllowOpenOptionsInGameplay.cs
@@ -2,7 +2,6 @@
using System.Reflection;
using HarmonyLib;
using JetBrains.Annotations;
-using Osu.Stubs;
using Osu.Stubs.Other;
using Osu.Utils.Extensions;
using static System.Reflection.Emit.OpCodes;
diff --git a/Osu.Patcher.Hook/Patches/UI/CustomSongSelectThumbnailAlpha.cs b/Osu.Patcher.Hook/Patches/UI/CustomSongSelectThumbnailAlpha.cs
index 65b923d..70e0d1e 100644
--- a/Osu.Patcher.Hook/Patches/UI/CustomSongSelectThumbnailAlpha.cs
+++ b/Osu.Patcher.Hook/Patches/UI/CustomSongSelectThumbnailAlpha.cs
@@ -3,7 +3,6 @@
using System.Reflection;
using HarmonyLib;
using JetBrains.Annotations;
-using Osu.Stubs;
using Osu.Stubs.SongSelect;
using Osu.Utils.Extensions;
using static System.Reflection.Emit.OpCodes;
diff --git a/Osu.Patcher.Hook/Patches/UI/RevertSortWhenNoGroup.cs b/Osu.Patcher.Hook/Patches/UI/RevertSortWhenNoGroup.cs
index 70273a9..4cc34de 100644
--- a/Osu.Patcher.Hook/Patches/UI/RevertSortWhenNoGroup.cs
+++ b/Osu.Patcher.Hook/Patches/UI/RevertSortWhenNoGroup.cs
@@ -3,7 +3,6 @@
using System.Reflection.Emit;
using HarmonyLib;
using JetBrains.Annotations;
-using Osu.Stubs;
using Osu.Stubs.Helpers;
using Osu.Stubs.SongSelect;
using Osu.Utils.Extensions;
diff --git a/Osu.Patcher.Hook/Patches/UI/ShowModsInGameplay.cs b/Osu.Patcher.Hook/Patches/UI/ShowModsInGameplay.cs
index 5b2b0d1..ecd48b7 100644
--- a/Osu.Patcher.Hook/Patches/UI/ShowModsInGameplay.cs
+++ b/Osu.Patcher.Hook/Patches/UI/ShowModsInGameplay.cs
@@ -3,7 +3,6 @@
using System.Reflection;
using HarmonyLib;
using JetBrains.Annotations;
-using Osu.Stubs;
using Osu.Stubs.GameModes;
using static System.Reflection.Emit.OpCodes;
diff --git a/Osu.Stubs.Tests/Osu.Stubs.Tests.csproj b/Osu.Stubs.Tests/Osu.Stubs.Tests.csproj
new file mode 100644
index 0000000..fb782ce
--- /dev/null
+++ b/Osu.Stubs.Tests/Osu.Stubs.Tests.csproj
@@ -0,0 +1,37 @@
+
+
+
+ Exe
+ Osu.Stubs.Tests
+ net462
+ x86
+ 12
+ enable
+
+
+ true
+ full
+ false
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ none
+ true
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers
+
+
+
diff --git a/Osu.Stubs.Tests/OsuApi.cs b/Osu.Stubs.Tests/OsuApi.cs
new file mode 100644
index 0000000..56ccf72
--- /dev/null
+++ b/Osu.Stubs.Tests/OsuApi.cs
@@ -0,0 +1,79 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Net.Http;
+using System.Threading.Tasks;
+using JetBrains.Annotations;
+using Newtonsoft.Json;
+
+namespace Osu.Stubs.Tests;
+
+[PublicAPI]
+public static class OsuApi
+{
+ [PublicAPI]
+ public enum ReleaseStream
+ {
+ CuttingEdge,
+ Stable40,
+ Beta40,
+ }
+
+ private static readonly HttpClient Http = new();
+
+ ///
+ /// Gets the latest release files for a specific release stream.
+ ///
+ public static async Task> GetReleaseFiles(ReleaseStream stream)
+ {
+ Console.WriteLine("Fetching latest osu! update info");
+
+ var url = $"https://osu.ppy.sh/web/check-updates.php" +
+ $"?action=check" +
+ $"&stream={stream.ToString().ToLower()}" +
+ $"&time={DateTime.Now.Ticks}";
+
+ using var response = await Http.GetAsync(url);
+ response.EnsureSuccessStatusCode();
+
+ var bodyText = await response.Content.ReadAsStringAsync();
+ if (bodyText == null) throw new Exception("Response returned no body");
+
+ var releaseFiles = JsonConvert.DeserializeObject>(bodyText);
+ if (releaseFiles == null) throw new Exception("Failed to deserialize update files");
+
+ return releaseFiles;
+ }
+
+ ///
+ /// Downloads the full osu! update file list to a specific directory.
+ ///
+ /// An empty directory.
+ /// The release stream to download.
+ public static async Task DownloadOsu(string dir, ReleaseStream stream = ReleaseStream.Stable40)
+ {
+ var updateFiles = await GetReleaseFiles(ReleaseStream.Stable40);
+
+ foreach (var updateFile in updateFiles)
+ {
+ Console.WriteLine($"Downloading {updateFile.FileName}");
+
+ await DownloadFile(
+ updateFile.DownloadUrl,
+ Path.Combine(dir, updateFile.FileName)
+ );
+ }
+ }
+
+ private static async Task DownloadFile(string url, string path)
+ {
+ using var response = await Http.GetAsync(url);
+ response.EnsureSuccessStatusCode();
+
+ var bodyStream = await response.Content.ReadAsStreamAsync();
+ if (bodyStream == null) throw new Exception("Response returned no body");
+
+ using var file = File.Create(path);
+ await bodyStream.CopyToAsync(file);
+ }
+}
\ No newline at end of file
diff --git a/Osu.Stubs.Tests/OsuUpdateFile.cs b/Osu.Stubs.Tests/OsuUpdateFile.cs
new file mode 100644
index 0000000..6804b17
--- /dev/null
+++ b/Osu.Stubs.Tests/OsuUpdateFile.cs
@@ -0,0 +1,30 @@
+using Newtonsoft.Json;
+
+namespace Osu.Stubs.Tests;
+
+public class OsuUpdateFile
+{
+ [JsonRequired]
+ [JsonProperty("file_version")]
+ public int FileVersion { get; set; }
+
+ [JsonRequired]
+ [JsonProperty("filesize")]
+ public int FileSize { get; set; }
+
+ [JsonRequired]
+ [JsonProperty("filename")]
+ public string FileName { get; set; } = null!;
+
+ [JsonRequired]
+ [JsonProperty("file_hash")]
+ public string FileHash { get; set; } = null!;
+
+ [JsonRequired]
+ [JsonProperty("timestamp")]
+ public string Timestamp { get; set; } = null!;
+
+ [JsonRequired]
+ [JsonProperty("url_full")]
+ public string DownloadUrl { get; set; } = null!;
+}
\ No newline at end of file
diff --git a/Osu.Stubs.Tests/Program.cs b/Osu.Stubs.Tests/Program.cs
new file mode 100644
index 0000000..da472cb
--- /dev/null
+++ b/Osu.Stubs.Tests/Program.cs
@@ -0,0 +1,49 @@
+using System;
+using System.IO;
+using System.Reflection;
+using System.Threading.Tasks;
+using Osu.Utils.Extensions;
+using Osu.Utils.Lazy;
+
+#pragma warning disable CS0618 // Type or member is obsolete
+
+namespace Osu.Stubs.Tests;
+
+internal static class Program
+{
+ private static async Task Main()
+ {
+ var osuDir = Path.Combine(Environment.CurrentDirectory, "osu!");
+ var osuExe = Path.Combine(osuDir, "osu!.exe");
+
+ if (!Directory.Exists(osuDir))
+ {
+ Directory.CreateDirectory(osuDir);
+ await OsuApi.DownloadOsu(osuDir);
+ }
+
+ AppDomain.CurrentDomain.AppendPrivatePath(osuDir);
+ Assembly.LoadFile(osuExe);
+
+ foreach (var type in Assembly.GetAssembly(typeof(Stub)).GetTypes())
+ {
+ foreach (var field in type.GetFields(BindingFlags.Public | BindingFlags.Static))
+ {
+ if (field.GetCustomAttribute(typeof(Stub)) == null)
+ continue;
+
+ var lazy = field.GetValue>(null);
+
+ try
+ {
+ Console.WriteLine($"{lazy.Name} -> {lazy.Reference}");
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine($"{lazy.Name} -> [Failure]");
+ Console.WriteLine(e);
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Osu.Stubs/Stub.cs b/Osu.Stubs/Stub.cs
index 331f53a..e7938db 100644
--- a/Osu.Stubs/Stub.cs
+++ b/Osu.Stubs/Stub.cs
@@ -4,7 +4,7 @@
namespace Osu.Stubs;
///
-/// Stub marker for a type extending .
+/// Stub marker for a type extending .
/// Used for testing stubs on new versions of osu!.
///
[AttributeUsage(AttributeTargets.Field)]
diff --git a/Osu.Utils/Lazy/LazyInfo.cs b/Osu.Utils/Lazy/ILazy.cs
similarity index 59%
rename from Osu.Utils/Lazy/LazyInfo.cs
rename to Osu.Utils/Lazy/ILazy.cs
index 8b200ca..89d59bc 100644
--- a/Osu.Utils/Lazy/LazyInfo.cs
+++ b/Osu.Utils/Lazy/ILazy.cs
@@ -8,7 +8,7 @@ namespace Osu.Utils.Lazy;
/// A base type for finding stuff with the use of reflection lazily.
///
[PublicAPI]
-public abstract class LazyInfo where T : MemberInfo
+public interface ILazy where T : MemberInfo
{
///
/// The assumed original human readable fully qualified name.
@@ -16,40 +16,45 @@ public abstract class LazyInfo where T : MemberInfo
///
public abstract string Name { get; }
- ///
- /// The runtime type name of the resolved reflective type.
- ///
- public string RuntimeName => Reference.Name;
-
///
/// Reference to the reflective target type.
/// This retrieves or finds the type when called.
///
public abstract T Reference { get; }
+}
+
+[PublicAPI]
+public static class LazyExtensions
+{
+ ///
+ /// Execute the lazy action to fill in the lazy value if not already done so.
+ ///
+ public static void Fill(this ILazy lazy) => _ = lazy.Reference;
///
/// Gets the result of a otherwise throws appropriate exceptions.
///
+ /// The ILazy instance, used for obtaining the ILazy implementor's name.
///
- ///
+ ///
///
- /// The lazy to invoke.
- /// Subtype of LazyInfo.
+ /// The lazy to invoke.
+ /// The result type of ILazy
/// The Lazy's result value
- protected static T GetReference(string name, Lazy lazy)
- where TL : LazyInfo
+ internal static T GetReference(this ILazy lazy, string name, Lazy realLazy)
+ where T : MemberInfo
{
try
{
- var value = lazy.Value;
+ var value = realLazy.Value;
if (value != null) return value;
- var lazyName = typeof(TL).Name;
+ var lazyName = lazy.GetType().Name;
throw new Exception($"{lazyName} result cannot be null!");
}
catch (Exception e)
{
- var lazyName = typeof(TL).Name;
+ var lazyName = lazy.GetType().Name;
throw new AggregateException($"Failed to run {lazyName} {name}", e);
}
}
diff --git a/Osu.Utils/Lazy/LazyConstructor.cs b/Osu.Utils/Lazy/LazyConstructor.cs
index c239aba..290f564 100644
--- a/Osu.Utils/Lazy/LazyConstructor.cs
+++ b/Osu.Utils/Lazy/LazyConstructor.cs
@@ -11,14 +11,14 @@ namespace Osu.Utils.Lazy;
/// A reference to a constructor that gets located at runtime and invoked reflectively.
///
[PublicAPI]
-public class LazyConstructor : LazyInfo
+public class LazyConstructor : ILazy
{
private readonly Lazy _lazy;
///
/// Make a wrapper around Lazy for constructor.
///
- /// of type what this is returning.
+ /// of type what this is returning.
/// The lazy action to run when the value is needed.
public LazyConstructor(string name, Func action)
{
@@ -26,9 +26,9 @@ public LazyConstructor(string name, Func action)
_lazy = new Lazy(action);
}
- public override string Name { get; }
+ public string Name { get; }
- public override ConstructorInfo Reference => GetReference(Name, _lazy);
+ public ConstructorInfo Reference => this.GetReference(Name, _lazy);
///
/// Find if not already cached and reflectively invoke this constructor to create a new instance of a class.
diff --git a/Osu.Utils/Lazy/LazyField.cs b/Osu.Utils/Lazy/LazyField.cs
index 358a883..b69acd8 100644
--- a/Osu.Utils/Lazy/LazyField.cs
+++ b/Osu.Utils/Lazy/LazyField.cs
@@ -9,7 +9,7 @@ namespace Osu.Utils.Lazy;
///
/// The type this field should be treated as.
[PublicAPI]
-public class LazyField : LazyInfo
+public class LazyField : ILazy
{
private readonly Lazy _lazy;
@@ -24,9 +24,9 @@ public LazyField(string name, Func action)
_lazy = new Lazy(action);
}
- public override string Name { get; }
+ public string Name { get; }
- public override FieldInfo Reference => GetReference>(Name, _lazy);
+ public FieldInfo Reference => this.GetReference(Name, _lazy);
///
/// Gets the current value of this field.
diff --git a/Osu.Utils/Lazy/LazyMethod.cs b/Osu.Utils/Lazy/LazyMethod.cs
index cc54f81..a1f86b7 100644
--- a/Osu.Utils/Lazy/LazyMethod.cs
+++ b/Osu.Utils/Lazy/LazyMethod.cs
@@ -11,14 +11,14 @@ namespace Osu.Utils.Lazy;
/// A reference to a method that gets located at runtime and invoked reflectively.
///
[PublicAPI]
-public class LazyMethod : LazyInfo
+public class LazyMethod : ILazy
{
private readonly Lazy _lazy;
///
/// Make a wrapper around Lazy for methods.
///
- /// of what type this is returning.
+ /// of what type this is returning.
/// The lazy action to run when the value is needed.
public LazyMethod(string name, Func action)
{
@@ -26,9 +26,9 @@ public LazyMethod(string name, Func action)
_lazy = new Lazy(action);
}
- public override string Name { get; }
+ public string Name { get; }
- public override MethodInfo Reference => GetReference(Name, _lazy);
+ public MethodInfo Reference => this.GetReference(Name, _lazy);
///
/// Find if not already cached and reflectively invoke this method. Does not return any value.
@@ -43,7 +43,7 @@ public void Invoke(object? instance = null, object?[]? parameters = null) =>
/// Searches every method to see if this is the entire method's bytecode.
///
///
- ///
+ ///
///
/// Sequential opcodes to compare the target method's bytecode with.
public static LazyMethod BySignature(string name, IReadOnlyList signature) =>
@@ -54,7 +54,7 @@ public static LazyMethod BySignature(string name, IReadOnlyList signatur
/// Searches every method to see if this is located in the method's bytecode.
///
///
- ///
+ ///
///
/// Sequential opcodes to search the target method with.
public static LazyMethod ByPartialSignature(string name, IReadOnlyList signature) =>
diff --git a/Osu.Utils/Lazy/LazyType.cs b/Osu.Utils/Lazy/LazyType.cs
index 6b1e40e..03e174f 100644
--- a/Osu.Utils/Lazy/LazyType.cs
+++ b/Osu.Utils/Lazy/LazyType.cs
@@ -7,7 +7,7 @@ namespace Osu.Utils.Lazy;
/// A reference to a Type that gets located at runtime and interacted with reflectively.
///
[PublicAPI]
-public class LazyType : LazyInfo
+public class LazyType : ILazy
{
private readonly Lazy _lazy;
@@ -22,15 +22,15 @@ public LazyType(string name, Func action)
_lazy = new Lazy(action);
}
- public override string Name { get; }
+ public string Name { get; }
- public override Type Reference => GetReference(Name, _lazy);
+ public Type Reference => this.GetReference(Name, _lazy);
///
/// Finds a class based on it's full name including namespace.
///
///
- ///
+ ///
///
///
/// The full runtime name to search for, including any namespaces. If this isn't different from
diff --git a/osu-patcher.sln b/osu-patcher.sln
index 11e495b..eb357b5 100644
--- a/osu-patcher.sln
+++ b/osu-patcher.sln
@@ -9,6 +9,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Osu.Stubs", "Osu.Stubs\Osu.
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Osu.Utils", "Osu.Utils\Osu.Utils.csproj", "{DBE8C9EB-4AC9-45A3-AFFF-A899A7A99823}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Osu.Stubs.Tests", "Osu.Stubs.Tests\Osu.Stubs.Tests.csproj", "{F60A9670-BD12-4FF9-A56B-AF564CFD8CCD}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x86 = Debug|x86
@@ -35,5 +37,9 @@ Global
{DBE8C9EB-4AC9-45A3-AFFF-A899A7A99823}.Debug|x86.Build.0 = Debug|Any CPU
{DBE8C9EB-4AC9-45A3-AFFF-A899A7A99823}.Release|x86.ActiveCfg = Release|Any CPU
{DBE8C9EB-4AC9-45A3-AFFF-A899A7A99823}.Release|x86.Build.0 = Release|Any CPU
+ {F60A9670-BD12-4FF9-A56B-AF564CFD8CCD}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {F60A9670-BD12-4FF9-A56B-AF564CFD8CCD}.Debug|x86.Build.0 = Debug|Any CPU
+ {F60A9670-BD12-4FF9-A56B-AF564CFD8CCD}.Release|x86.ActiveCfg = Release|Any CPU
+ {F60A9670-BD12-4FF9-A56B-AF564CFD8CCD}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal