Commit e0145be7 authored by UnityMethodPatcher CI's avatar UnityMethodPatcher CI
Browse files

[CI] Changes for 1-12-11

Showing with 59 additions and 21 deletions
+59 -21
......@@ -34,7 +34,7 @@ namespace SingularityGroup.HotReload.Editor {
public static void RegisterLogin(LoginStatusResponse response) {
//Licensing might not be initialized yet.
//The hwId should be set eventually.
if(response.hardwareId == null) {
if(response?.hardwareId == null) {
return;
}
//Only forward attribution if this is an asset store build.
......
......@@ -22,8 +22,8 @@ using UnityEngine.SceneManagement;
namespace SingularityGroup.HotReload {
class RegisterPatchesResult {
public readonly List<SMethod> patchedMethods = new List<SMethod>();
public readonly List<SMethod> addedMethods = new List<SMethod>();
// note: doesn't include removals and method definition changes (e.g. renames)
public readonly List<MethodPatch> patchedMethods = new List<MethodPatch>();
public readonly List<Tuple<SMethod, string>> patchFailures = new List<Tuple<SMethod, string>>();
}
......@@ -114,7 +114,7 @@ namespace SingularityGroup.HotReload {
count += response.patches.Length;
}
if (count > 0) {
Dispatch.OnHotReload().Forget();
Dispatch.OnHotReload(result.patchedMethods).Forget();
}
} catch(Exception ex) {
Log.Warning("Exception occured when handling method patch. Exception:\n{0}", ex);
......@@ -163,7 +163,9 @@ namespace SingularityGroup.HotReload {
}
MethodUtils.DisableVisibilityChecks(newMethod);
if (!patch.patchMethods.Any(m => m.metadataToken == sMethod.metadataToken)) {
result.addedMethods.Add(sMethod);
result.patchedMethods.Add(new MethodPatch(null, null, newMethod));
previousPatchMethods[newMethod] = newMethod;
newMethods.Add(newMethod);
}
}
......@@ -183,6 +185,9 @@ namespace SingularityGroup.HotReload {
}
}
Dictionary<MethodBase, MethodBase> previousPatchMethods = new Dictionary<MethodBase, MethodBase>();
List<MethodBase> newMethods = new List<MethodBase>();
string PatchMethod(Module module, SMethod sOriginalMethod, SMethod sPatchMethod, bool containsBurstJobs, RegisterPatchesResult patchesResult) {
try {
var patchMethod = module.ResolveMethod(sPatchMethod.metadataToken);
......@@ -208,7 +213,18 @@ namespace SingularityGroup.HotReload {
DetourResult result;
DetourApi.DetourMethod(state.match, patchMethod, out result);
if (result.success) {
patchesResult.patchedMethods.Add(sOriginalMethod);
// previous method is either original method or the last patch method
MethodBase previousMethod;
if (!previousPatchMethods.TryGetValue(state.match, out previousMethod)) {
previousMethod = state.match;
}
MethodBase originalMethod = state.match;
if (newMethods.Contains(state.match)) {
// for function added at runtime the original method should be null
originalMethod = null;
}
patchesResult.patchedMethods.Add(new MethodPatch(originalMethod, previousMethod, patchMethod));
previousPatchMethods[state.match] = patchMethod;
try {
Dispatch.OnHotReloadLocal(state.match, patchMethod);
} catch {
......
......@@ -16,16 +16,15 @@ namespace SingularityGroup.HotReload {
static class Dispatch {
// DispatchOnHotReload is called every time a patch is applied (1x per batch of filechanges)
// Currently, we don't support [InvokeOnHotReload] on patched methods
public static async Task OnHotReload() {
public static async Task OnHotReload(List<MethodPatch> patchedMethods) {
var methods = await Task.Run(() => GetOrFillMethodsCacheThreaded());
foreach (var m in methods) {
if (m.IsStatic) {
InvokeStaticMethod(m, nameof(InvokeOnHotReload));
InvokeStaticMethod(m, nameof(InvokeOnHotReload), patchedMethods);
} else {
foreach (var go in GameObject.FindObjectsOfType(m.DeclaringType)) {
InvokeInstanceMethod(m, go);
InvokeInstanceMethod(m, go, patchedMethods);
}
}
}
......@@ -43,7 +42,7 @@ namespace SingularityGroup.HotReload {
}
var patchMethodParams = patchMethod.GetParameters();
if (patchMethodParams.Length == 0) {
InvokeStaticMethod(patchMethod, nameof(InvokeOnHotReloadLocal));
InvokeStaticMethod(patchMethod, nameof(InvokeOnHotReloadLocal), null);
} else if (typeof(MonoBehaviour).IsAssignableFrom(patchMethodParams[0].ParameterType)) {
foreach (var go in GameObject.FindObjectsOfType(patchMethodParams[0].ParameterType)) {
InvokeInstanceMethodStatic(patchMethod, go);
......@@ -62,10 +61,10 @@ namespace SingularityGroup.HotReload {
return;
}
if (reloadMethod.IsStatic) {
InvokeStaticMethod(reloadMethod, nameof(InvokeOnHotReloadLocal));
InvokeStaticMethod(reloadMethod, nameof(InvokeOnHotReloadLocal), null);
} else if (typeof(MonoBehaviour).IsAssignableFrom(reloadForType)) {
foreach (var go in GameObject.FindObjectsOfType(reloadForType)) {
InvokeInstanceMethod(reloadMethod, go);
InvokeInstanceMethod(reloadMethod, go, null);
}
} else {
Log.Warning($"[{nameof(InvokeOnHotReloadLocal)}] {reloadMethod.DeclaringType?.Name} {reloadMethod.Name} failed. Make sure it's a method with 0 parameters either static or defined on MonoBehaviour.");
......@@ -146,24 +145,32 @@ namespace SingularityGroup.HotReload {
return methods;
}
private static void InvokeStaticMethod(MethodBase m, string attrName) {
private static void InvokeStaticMethod(MethodBase m, string attrName, List<MethodPatch> patchedMethods) {
try {
m.Invoke(null, new object[] { });
if (patchedMethods != null && m.GetParameters().Length == 1) {
m.Invoke(null, new object[] { patchedMethods });
} else {
m.Invoke(null, new object[] { });
}
} catch (Exception e) {
if (m.GetParameters().Length != 0) {
Log.Warning($"[{attrName}] {m.DeclaringType?.Name} {m.Name} failed. Make sure it has 0 parameters. Exception:\n{e}");
Log.Warning($"[{attrName}] {m.DeclaringType?.Name} {m.Name} failed. Make sure it has 0 parameters, or 1 parameter with type List<MethodPatch>. Exception:\n{e}");
} else {
Log.Warning($"[{attrName}] {m.DeclaringType?.Name} {m.Name} failed. Exception\n{e}");
}
}
}
private static void InvokeInstanceMethod(MethodBase m, Object go) {
private static void InvokeInstanceMethod(MethodBase m, Object go, List<MethodPatch> patchedMethods) {
try {
m.Invoke(go, new object[] { });
if (patchedMethods != null && m.GetParameters().Length == 1) {
m.Invoke(go, new object[] { patchedMethods });
} else {
m.Invoke(go, new object[] { });
}
} catch (Exception e) {
if (m.GetParameters().Length != 0) {
Log.Warning($"[InvokeOnHotReload] {m.DeclaringType?.Name} {m.Name} failed. Make sure it has 0 parameters. Exception:\n{e}");
Log.Warning($"[InvokeOnHotReload] {m.DeclaringType?.Name} {m.Name} failed. Make sure it has 0 parameters, or 1 parameter with type List<MethodPatch>. Exception:\n{e}");
} else {
Log.Warning($"[InvokeOnHotReload] {m.DeclaringType?.Name} {m.Name} failed. Exception:\n{e}");
}
......
......@@ -8,7 +8,7 @@ namespace SingularityGroup.HotReload {
public static bool IsAssetStoreBuild => false;
public const string Version = "1.12.10";
public const string Version = "1.12.11";
// Never higher than Version
// Used for the download
public const string ServerVersion = "1.12.10";
......
using System;
using System.Reflection;
namespace SingularityGroup.HotReload {
/// <summary>
......@@ -14,4 +15,18 @@ namespace SingularityGroup.HotReload {
public class InvokeOnHotReload : Attribute {
}
public class MethodPatch {
// Compiled by the Unity Editor. Null for newly added methods.
public MethodBase originalMethod;
// Method before Hot Reload applied it's patch. Null for newly added methods.
public MethodBase previousMethod;
// Method generated by Hot Reload.
public MethodBase newMethod;
public MethodPatch(MethodBase originalMethod, MethodBase previousMethod, MethodBase newMethod) {
this.originalMethod = originalMethod;
this.previousMethod = previousMethod;
this.newMethod = newMethod;
}
}
}
......@@ -12,7 +12,7 @@
"sg",
"singularity"
],
"version": "1.12.10",
"version": "1.12.11",
"dependencies": {
"com.unity.ugui": "1.0.0",
"com.unity.modules.unitywebrequest": "1.0.0"
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment