using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Security.Cryptography; using System.Text; using BepInEx.Configuration; using HarmonyLib; using undead_universal_patch_il2cpp.Core.Config; namespace undead_universal_patch_il2cpp.Core { public class PatchTypesResult { public string Description; public Type Type; public MethodInfo Method; public bool Success; } public class Util { private static readonly PatchTypesResult UnsuccessfulPatchResult = new() { Type = null, Method = null, Success = false }; public static string LocalInstanceGuid { set; get; } public static void ConditionalDebug(string msg) { if (GenericConfig.PatchDebug.Value) UniversalPatchPlugin.Log.LogDebug(msg); } public static PatchTypesResult ConfigsPreparePatchTypes(ConfigEntry[] config, string description, string targetTypeName, string methodName) { if (config.All(conf => conf.Value)) return VerifyPatchTypes(description, targetTypeName, methodName); else return UnsuccessfulPatchResult; } public static PatchTypesResult ConfigPreparePatchTypes(ConfigEntry config, string description, string targetTypeName, string methodName) { if (config.Value) return VerifyPatchTypes(description, targetTypeName, methodName); else return UnsuccessfulPatchResult; } public static PatchTypesResult PreparePatchTypes(string description, string targetTypeName, string methodName) { return VerifyPatchTypes(description, targetTypeName, methodName); } public static PatchTypesResult PreparePatchSpecificTypes(string description, string targetTypeName, string methodName, string[] generics) { return VerifyPatchTypes(description, targetTypeName, methodName, [.. generics]); } private static PatchTypesResult VerifyPatchTypes(string description, string targetTypeName, string methodName, List generics = null) { ConditionalDebug($"Loading patch '{description}'"); Type targetType = AccessTools.TypeByName(targetTypeName); if (targetType == null) { UniversalPatchPlugin.Log.LogWarning($"Patch '{description}' disabled. The type for this patch was not found."); return UnsuccessfulPatchResult; } List types = null; if (generics != null) { types = generics.Select(AccessTools.TypeByName).ToList(); if (!types.All(type => type != null)) { UniversalPatchPlugin.Log.LogWarning($"Patch '{description}' disabled. One or more generics for this patch were not found."); return UnsuccessfulPatchResult; } } MethodInfo method; if (generics != null && types != null) { ConditionalDebug($"Fetching method type: Type '{targetType.Name}', Method '{methodName}', Generics: {types.Count}"); method = AccessTools.Method(targetType, methodName, [.. types]); } else { ConditionalDebug($"Fetching method type: Type '{targetType.Name}', Method '{methodName}'"); method = AccessTools.Method(targetType, methodName); } if (method == null) { UniversalPatchPlugin.Log.LogWarning($"Patch '{description}' disabled. The method for this patch was not found."); return UnsuccessfulPatchResult; } UniversalPatchPlugin.Log.LogInfo($"Patch '{description}' succeeded validation."); return new PatchTypesResult { Description = description, Type = targetType, Method = method, Success = true }; } public static PatchTypesResult PostRequireTypes(PatchTypesResult result, object[] objects) { if (result.Success) { if (!objects.All(obj => obj != null)) { UniversalPatchPlugin.Log.LogError($"'{result.Description}' failed: A postrequire type was not found."); return UnsuccessfulPatchResult; } else return result; } else return UnsuccessfulPatchResult; } } }