diff --git a/R2API.Test/ReflectionTests.cs b/R2API.Test/ReflectionTests.cs
index 1db5de09..8e24d622 100644
--- a/R2API.Test/ReflectionTests.cs
+++ b/R2API.Test/ReflectionTests.cs
@@ -199,16 +199,11 @@ public void TestReflectionStructPublicPropertyGetAndSet() {
[Fact]
public void TestReflectionItemDropAPI() {
- var method = typeof(PickupIndex).GetMethodCached("get_itemIndex");
- Assert.NotNull(method);
-
-
- var nextElementUniform = typeof(Xoroshiro128Plus)
- .GetMethods()
- .First(x => x.Name == "NextElementUniform"
- && x.GetParameters()[0].ParameterType.GUID == typeof(List<>).GUID);
-
+ var nextElementUniform = typeof(Xoroshiro128Plus).GetMethodWithConstructedGenericParameter("NextElementUniform", typeof(List<>));
Assert.NotNull(nextElementUniform);
+
+ var nextElementUniformExact = nextElementUniform.MakeGenericMethod(typeof(PickupIndex));
+ Assert.NotNull(nextElementUniformExact);
}
[Fact]
diff --git a/R2API/ItemDropAPI.cs b/R2API/ItemDropAPI.cs
index a6819fcf..835fd720 100644
--- a/R2API/ItemDropAPI.cs
+++ b/R2API/ItemDropAPI.cs
@@ -242,19 +242,19 @@ private static void RunOnBuildDropTable(On.RoR2.Run.orig_BuildDropTable orig, Ru
}
// These lists should be replaced soon.
self.availableTier1DropList.Clear();
- self.availableTier1DropList.AddRange(GetDefaultDropList(ItemTier.Tier1).Select(x => PickupCatalog.FindPickupIndex(x))
+ self.availableTier1DropList.AddRange(GetDefaultDropList(ItemTier.Tier1).Select(PickupCatalog.FindPickupIndex)
.ToList());
self.availableTier2DropList.Clear();
- self.availableTier2DropList.AddRange(GetDefaultDropList(ItemTier.Tier2).Select(x => PickupCatalog.FindPickupIndex(x))
+ self.availableTier2DropList.AddRange(GetDefaultDropList(ItemTier.Tier2).Select(PickupCatalog.FindPickupIndex)
.ToList());
self.availableTier3DropList.Clear();
- self.availableTier3DropList.AddRange(GetDefaultDropList(ItemTier.Tier3).Select(x => PickupCatalog.FindPickupIndex(x))
+ self.availableTier3DropList.AddRange(GetDefaultDropList(ItemTier.Tier3).Select(PickupCatalog.FindPickupIndex)
.ToList());
self.availableEquipmentDropList.Clear();
- self.availableEquipmentDropList.AddRange(GetDefaultEquipmentDropList().Select(x => PickupCatalog.FindPickupIndex(x))
+ self.availableEquipmentDropList.AddRange(GetDefaultEquipmentDropList().Select(PickupCatalog.FindPickupIndex)
.ToList());
self.availableLunarDropList.Clear();
@@ -290,21 +290,14 @@ private static void DropRewards(ILContext il) {
cursor.Emit(OpCodes.Stloc_0);
- cursor.GotoNext(x => x.MatchCall(typeof(PickupIndex).GetMethodCached("get_itemIndex")));
-
- var itemIndex = Reflection.ReadLocalIndex(cursor.Next.Next.OpCode, cursor.Next.Next.Operand);
-
- cursor.GotoNext(x => x.MatchCall(typeof(PickupIndex).GetConstructorCached(new[] { typeof(ItemIndex) })));
- cursor.GotoPrev(x => x.OpCode == OpCodes.Ldloca_S);
-
- var pickupIndex = (VariableDefinition)cursor.Next.Operand;
+ var nextElementUniform = typeof(Xoroshiro128Plus)
+ .GetMethodWithConstructedGenericParameter("NextElementUniform", typeof(List<>))
+ .MakeGenericMethod(typeof(PickupIndex));
+ cursor.GotoNext(MoveType.After, x => x.MatchCallOrCallvirt(nextElementUniform));
+ var pickupIndex = Reflection.ReadLocalIndex(cursor.Next.OpCode, cursor.Next.Operand);
cursor.Goto(0);
- cursor.GotoNext(x => x.MatchStloc(itemIndex));
- cursor.Emit(OpCodes.Stloc_S, itemIndex);
-
-
cursor.Emit(OpCodes.Ldarg_0);
cursor.Emit(OpCodes.Dup);
cursor.Emit(OpCodes.Ldfld, typeof(BossGroup).GetFieldCached("rng"));
@@ -321,8 +314,6 @@ private static void DropRewards(ILContext il) {
});
cursor.Emit(OpCodes.Stloc_S, pickupIndex);
- cursor.Emit(OpCodes.Ldloca_S, pickupIndex);
- cursor.Emit(OpCodes.Call, typeof(PickupIndex).GetMethodCached("get_itemIndex"));
}
public static void AddDrops(ItemDropLocation dropLocation, params PickupSelection[] pickups) {
diff --git a/R2API/R2API.cs b/R2API/R2API.cs
index 13447931..66948481 100644
--- a/R2API/R2API.cs
+++ b/R2API/R2API.cs
@@ -23,7 +23,7 @@ public class R2API : BaseUnityPlugin {
public const string PluginVersion = "0.0.1";
- private const int GameBuild = 4892828;
+ private const int GameBuild = 5381045;
internal new static ManualLogSource Logger { get; set; }
@@ -107,9 +107,9 @@ public static bool IsLoaded(string submodule) {
}
private static void AddHookLogging() {
- ModManager.OnHook += (hookOwner, @base, arg3, arg4) => LogMethod(@base, hookOwner);
- ModManager.OnDetour += (hookOwner, @base, arg3) => LogMethod(@base, hookOwner);
- ModManager.OnNativeDetour += (hookOwner, @base, arg3, arg4) => LogMethod(@base, hookOwner);
+ ModManager.OnHook += (hookOwner, @base, _, __) => LogMethod(@base, hookOwner);
+ ModManager.OnDetour += (hookOwner, @base, _) => LogMethod(@base, hookOwner);
+ ModManager.OnNativeDetour += (hookOwner, @base, _, __) => LogMethod(@base, hookOwner);
HookEndpointManager.OnAdd += (@base, @delegate) => LogMethod(@base, @delegate.Method.Module.Assembly);
HookEndpointManager.OnModify += (@base, @delegate) => LogMethod(@base, @delegate.Method.Module.Assembly);
diff --git a/R2API/R2API.csproj b/R2API/R2API.csproj
index 6e94ff64..473d2d23 100644
--- a/R2API/R2API.csproj
+++ b/R2API/R2API.csproj
@@ -2,7 +2,7 @@
netstandard2.0
- 7.2
+ preview
2.0.0
diff --git a/R2API/Utils/Reflection.cs b/R2API/Utils/Reflection.cs
index ce9c0ab9..78cdf546 100644
--- a/R2API/Utils/Reflection.cs
+++ b/R2API/Utils/Reflection.cs
@@ -362,11 +362,34 @@ public static MethodInfo GetMethodCached(string name) =>
///
/// The type to search
/// The name of the method to find
- ///
+ /// The found
public static MethodInfo GetMethodCached(this Type T, string name) =>
MethodCache.GetOrAddOnNull((T, name), x => x.T.GetMethod(x.name, AllFlags)
?? throw new Exception($"Could not find {nameof(MethodInfo)} on {T.FullName} with the name {name}"));
+ ///
+ /// Gets the generic method of the specified type with the specified generic type definition parameter
+ ///
+ /// The type to search
+ /// The name of the method to find
+ /// The generic type definition parameter
+ /// The found
+ public static MethodInfo GetMethodWithConstructedGenericParameter(this Type T, string name, Type genericTypeDefinition) {
+ return T.GetMethods().First(method => {
+ if (method.Name != name) {
+ return false;
+ }
+
+ var parameterType = method.GetParameters().First().ParameterType;
+ if (!parameterType.IsConstructedGenericType) {
+ return false;
+ }
+
+ var t = parameterType.GetGenericArguments().First();
+ return parameterType == genericTypeDefinition.MakeGenericType(t);
+ });
+ }
+
///
/// Gets the method on the specified type and caches it. This overload is used when the method is ambiguous
///
@@ -777,7 +800,7 @@ private static FastReflectionDelegate GenerateCallDelegate(this MethodInfo metho
throw new ArgumentException("Method cannot be null.", nameof(method));
}
- var dmd = new DynamicMethodDefinition(
+ using var dmd = new DynamicMethodDefinition(
$"CallDelegate<{method.Name}>", typeof(object), new[] { typeof(object), typeof(object[]) });
var il = dmd.GetILProcessor();