public static void OnXXXLoad() { var harmony = HarmonyInstance.Create("test"); var transpiler = new HarmonyMethod(typeof(Time_test).GetMethod(nameof(Transpiler))); var originals = AccessTools.GetDeclaredMethods(typeof(GameClock)); originals.AddRange(AccessTools.GetDeclaredMethods(typeof(TimerSideScreen))); originals.AddRange(AccessTools.GetDeclaredMethods(typeof(ReportManager))); //originals.AddRange(AccessTools.GetDeclaredMethods(typeof(EconomyDetails))); originals.AddRange(AccessTools.GetDeclaredMethods(typeof(TimeRangeSideScreen))); originals.Add(AccessTools.Method(typeof(GameUtil), nameof(GameUtil.ApplyTimeSlice))); originals.Add(AccessTools.Method("ColonyDiagnosticScreen.DiagnosticRow:DiagnosticRow")); foreach (var original in originals) { if (original == null) { Debug.Log("wups it's a null"); continue; } try { Debug.Log("[CustomGameClock] Patching " + original.Name); harmony.Patch(original, transpiler: transpiler); } catch (Exception) { } } Debug.Log("[CustomGameClock] DONE"); }
public static void InventoryIngredients(CharacterInventory __instance, Tag _craftingStationTag, ref DictionaryExt <int, CompatibleIngredient> _sortedIngredient) { try { if (InnRentStash.CurrentStash == null || !InnRentStash.CurrentStash.IsInteractable || !InnRentStash.Instance.ConfigStashSharing.Value) { return; } //InnRentStash.MyLogger.LogDebug($"InventoryIngredients for {_craftingStationTag}"); /*foreach (var m in AccessTools.GetDeclaredMethods(typeof(CharacterInventory))) * { * InnRentStash.MyLogger.LogDebug($"{m.Name}"); * if (m.Name == "InventoryIngredients") * { * foreach (var p in m.GetParameters()) * { * InnRentStash.MyLogger.LogDebug($" |- {p.Name} {p.IsOut} {p}"); * } * } * }*/ MethodInfo mi = AccessTools.GetDeclaredMethods(typeof(CharacterInventory)).FirstOrDefault(m => m.Name == "InventoryIngredients" && m.GetParameters().Any(p => p.Name == "_items")); //InnRentStash.MyLogger.LogDebug($"{mi}"); //InnRentStash.MyLogger.LogDebug($"Before={_sortedIngredient.Count}"); mi.Invoke(__instance, new object[] { _craftingStationTag, _sortedIngredient, InnRentStash.CurrentStash.GetContainedItems() }); //InnRentStash.MyLogger.LogDebug($"After={_sortedIngredient.Count}"); } catch (Exception ex) { InnRentStash.MyLogger.LogError("InventoryIngredients: " + ex.Message); } }
public static void UnPatchTypePatches(Type type) { foreach (MethodInfo method in AccessTools.GetDeclaredMethods(type)) { UnpatchMethodsOnMethod(method); } }
public static IEnumerable <MethodBase> TargetMethods() { return(AccessTools.GetDeclaredMethods(typeof(Widgets)) .Where(m => m.GetParameters().Any(p => p.ParameterType == typeof(Rect))) .SelectMany(m => { if (m.IsGenericMethod == false) { return new List <MethodInfo> { m } } ; if (m.Name == "Dropdown") { return new List <MethodInfo>() { m.MakeGenericMethod(typeof(Bill_Production), typeof(Zone_Stockpile)), m.MakeGenericMethod(typeof(Pawn), typeof(DrugPolicy)), m.MakeGenericMethod(typeof(Pawn), typeof(HostilityResponseMode)), m.MakeGenericMethod(typeof(Pawn), typeof(MedicalCareCategory)), m.MakeGenericMethod(typeof(Pawn), typeof(FoodRestriction)), m.MakeGenericMethod(typeof(Pawn), typeof(Outfit)), m.MakeGenericMethod(typeof(Pawn), typeof(Pawn)) } } ; return new List <MethodInfo>() { m.MakeGenericMethod(typeof(int)), m.MakeGenericMethod(typeof(float)) }; })); }
/********* ** Private methods *********/ /// <summary>Raised after the game is launched, right before the first update tick. This happens once per game session (unrelated to loading saves). All mods are loaded and initialized at this point, so this is a good time to set up mod integrations.</summary> /// <param name="sender">The event sender.</param> /// <param name="e">The event data.</param> private void OnGameLaunched(object sender, GameLaunchedEventArgs e) { IAutomateAPI automate = Helper.ModRegistry.GetApi <IAutomateAPI>("Pathoschild.Automate"); automate.AddFactory(new ProducerFrameworkAutomationFactory()); var harmony = HarmonyInstance.Create("Digus.PFMAutomate"); Assembly automateAssembly = AppDomain.CurrentDomain.GetAssemblies().First(a => a.FullName.StartsWith("Automate,")); MethodInfo automateMethodInfo = AccessTools.GetDeclaredMethods(automateAssembly.GetType("Pathoschild.Stardew.Automate.Framework.AutomationFactory")).Find(m => m.GetParameters().Any(p => p.ParameterType == typeof(SObject))); harmony.Patch( original: automateMethodInfo, postfix: new HarmonyMethod(typeof(AutomateOverrides), nameof(AutomateOverrides.GetFor)) ); Assembly ccrmAutomateAssembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(a => a.FullName.StartsWith("CCRMAutomate,")); if (ccrmAutomateAssembly != null) { MethodInfo ccrmAutomateMethodInfo = AccessTools.GetDeclaredMethods(ccrmAutomateAssembly.GetType("CCRMAutomate.Automate.CustomCrystalariumAutomationFactory")).Find(m => m.GetParameters().Any(p => p.ParameterType == typeof(SObject))); harmony.Patch( original: ccrmAutomateMethodInfo, postfix: new HarmonyMethod(typeof(CCRMAutomateOverrides), nameof(CCRMAutomateOverrides.GetFor)) ); } }
protected override void Apply(Harmony harmony) { harmony.Patch( original: AccessTools.GetDeclaredMethods(typeof(Game1)).Find(MatchGetCharacterFromNameMethod), postfix: new HarmonyMethod(typeof(GetCharacterPatch), nameof(GetCharacterPatch.After_getCharacterFromName)) ); }
/// <summary> /// Applies harmony patches on startup. /// </summary> /// <param name="harmony">Our instance of harmony to patch with.</param> public Cutebold_Patch_Stats(Harmony harmony) { var settings = Cutebold_Assemblies.CuteboldSettings; if (settings.extraYield && ModLister.GetActiveModWithIdentifier("syrchalis.harvestyieldpatch") == null) { if (settings.eyeAdaptation) { adaptation = true; // Insert Dark Adaptation bonus yield explination harmony.Patch(AccessTools.Method(typeof(StatWorker), "GetExplanationUnfinalized"), postfix: new HarmonyMethod(typeof(Cutebold_Patch_Stats), "CuteboldGetExplanationUnfinalizedPostfix")); } if (settings.altYield) // Use Postfixes { // Tweaks Mining Yield for Cutebolds harmony.Patch(AccessTools.Method(typeof(Mineable), "TrySpawnYield"), postfix: new HarmonyMethod(typeof(Cutebold_Patch_Stats), "CuteboldTrySpawnYieldMiningPostfix")); // Tweaks Harvist Yield for Cutebolds harmony.Patch(AccessTools.Method(typeof(JobDriver_PlantWork), "MakeNewToils"), postfix: new HarmonyMethod(typeof(Cutebold_Patch_Stats), "CuteboldMakeNewToilsPlantWorkPostfix")); } else // Use Transpilers { // Tweaks Mining Yield for Cutebolds harmony.Patch(AccessTools.Method(typeof(Mineable), "TrySpawnYield"), transpiler: new HarmonyMethod(typeof(Cutebold_Patch_Stats), "CuteboldTrySpawnYieldMiningTranspiler")); // Tweaks Harvist Yield for Cutebolds var plantWorkToilMethod = AccessTools.GetDeclaredMethods(typeof(JobDriver_PlantWork).GetNestedTypes(AccessTools.all).First()).ElementAt(1); harmony.Patch(plantWorkToilMethod, transpiler: new HarmonyMethod(typeof(Cutebold_Patch_Stats), "CuteboldMakeNewToilsPlantWorkTranspiler")); } // Edits the stats in the stat bio window to be the correct value. harmony.Patch(AccessTools.Method(typeof(StatsReportUtility), "StatsToDraw", new[] { typeof(Thing) }), postfix: new HarmonyMethod(typeof(Cutebold_Patch_Stats), "CuteboldStatsToDrawPostfix")); } }
public static IEnumerable <MethodInfo> GetTypeMethods(Type type) { foreach (var method in AccessTools.GetDeclaredMethods(type).Where(ValidMethod)) { yield return(method); } }
public static void FindUnpatchedInType(Type type, string[] unsupportedTypes, List <string> systemRngLog, List <string> unityRngLog, List <string> logAllClasses = null) { // Don't mind all the try/catch blocks, I went for maximum safety try { if (unsupportedTypes.Any(t => type.Namespace != null && (type.Namespace == t || type.Namespace.StartsWith($"{t}.")))) { return; } } catch (Exception) { // ignored } if (logAllClasses != null) { lock (logAllClasses) logAllClasses.Add(type.FullName); } try { // Get all methods, constructors, getters, and setters (everything that should have IL instructions) var methods = AccessTools.GetDeclaredMethods(type).Cast <MethodBase>() .Concat(AccessTools.GetDeclaredConstructors(type)) .Concat(AccessTools.GetDeclaredProperties(type).SelectMany(p => new[] { p.GetGetMethod(true), p.GetSetMethod(true) }).Where(p => p != null)); foreach (var method in methods) { try { MpCompat.harmony.Patch(method, transpiler: new HarmonyMethod(typeof(DebugActions), nameof(FindRng))); } catch (Exception e) when((e?.InnerException ?? e) is PatchingCancelledException cancelled) { if (cancelled.foundSystemRng) { lock (systemRngLog) systemRngLog.Add($"{type.FullName}:{method.Name}"); } if (cancelled.foundUnityRng) { lock (unityRngLog) unityRngLog.Add($"{type.FullName}:{method.Name}"); } } catch (Exception) { // ignored } } } catch (Exception) { // ignored } }
public static void Init() { var i = HarmonyWrapper.PatchAll(typeof(Hooks)); foreach (var target in AccessTools.GetDeclaredMethods(typeof(ShapeInfoBase)).Where(x => x.Name == nameof(ShapeInfoBase.ChangeValue))) { i.Patch(target, null, new HarmonyMethod(typeof(Hooks), nameof(ChangeValuePost))); } }
public static void InitHooks() { MethodInfo TryMethod(Type type, string name, Type[] parameters = null, Type[] generics = null) { return(type == null ? null : AccessTools.Method(type, name, parameters, generics)); } var hi = Harmony.CreateAndPatchAll(typeof(Hooks), GamepadSupportPlugin.Guid + ".CanvasCharmer"); // Fix keyboard navigation not working in chara/map lists var handlerPost = AccessTools.Method(typeof(Hooks), nameof(SetToggleHandlerPost)); foreach (var methodInfo in new[] { // Some are KK or KKP specific, hence why not using typeof TryMethod(Type.GetType("ActionGame.ClassRoomFileListCtrl, Assembly-CSharp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", false), "SetToggleHandler", new[] { typeof(GameObject) }), TryMethod(Type.GetType("StaffRoom.StaffRoomCharaListCtrl, Assembly-CSharp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", false), "SetToggleHandler", new[] { typeof(GameObject) }), TryMethod(Type.GetType("StaffRoom.StaffRoomMapListCtrl, Assembly-CSharp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", false), "SetToggleHandler", new[] { typeof(GameObject) }), TryMethod(Type.GetType("ChaCustom.CustomSelectListCtrl, Assembly-CSharp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", false), "SetToggleHandler", new[] { typeof(GameObject) }), TryMethod(Type.GetType("ExternalFile.ExternalFileListCtrl, Assembly-CSharp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", false), "SetToggleHandler", new[] { typeof(GameObject) }), TryMethod(Type.GetType("EmblemSelectListCtrl, Assembly-CSharp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", false), "SetToggleHandler", new[] { typeof(GameObject) }), TryMethod(Type.GetType("UGUI_AssistLibrary.UIAL_ListCtrl, Assembly-CSharp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", false), "SetToggleHandler", new[] { typeof(GameObject) }), }) { if (methodInfo != null) { hi.Patch(methodInfo, null, new HarmonyMethod(handlerPost)); } } // KKP specific, has a MonoB argument instead of GameObj like others var listType = Type.GetType("FileListUI.ThreadFileListCtrl`2[[ChaCustom.CustomFileInfo, Assembly-CSharp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null],[ChaCustom.CustomFileInfoComponent, Assembly-CSharp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]], Assembly-CSharp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", false); if (listType != null) { var kkpList = AccessTools.Method(listType, "SetToggleHandler"); if (kkpList != null) { hi.Patch(kkpList, null, new HarmonyMethod(AccessTools.Method(typeof(Hooks), nameof(SetToggleHandlerPostForParty)))); } } // Fix keyboard navigation not working in HSprite / h scene var hspriteTargets = AccessTools.GetDeclaredMethods(typeof(HSprite)); var mouseKillerTpl = AccessTools.Method(typeof(Hooks), nameof(MouseCheckKillerTpl)); foreach (var mName in _hSpriteKillList) { foreach (var m in hspriteTargets.Where(x => x.Name == mName)) { hi.Patch(m, null, null, new HarmonyMethod(mouseKillerTpl)); } } }
public void LinkTypes(Type originalType, Type targetType, object targetForAllInstances = null) { if (TracedTypes.Any(tt => tt.FromType == originalType && tt.ToType == targetType)) { return; } TracedTypes.Add(new TypeForwarding(originalType, targetType, Plato, targetForAllInstances)); foreach (MethodInfo tmethod in AccessTools.GetDeclaredMethods(targetType)) { if (AccessTools.Method(originalType, tmethod.Name, tmethod.GetParameters().Select(p => p.ParameterType).ToArray(), null) is MethodInfo method && method.GetParameters() is ParameterInfo[] parameters) { if (TracedMethods.Contains(method)) { continue; } else { TracedMethods.Add(method); } if (!method.IsDeclaredMember()) { method = method.DeclaringType.GetMethod(method.Name, method.GetParameters().Select(p => p.ParameterType).ToArray()); } bool hasReturnType = method.ReturnType != Type.GetType("System.Void"); List <Type> patchParameters = new List <Type>(); List <Type> genericParameters = new List <Type>(); if (hasReturnType) { genericParameters.Add(method.ReturnType); patchParameters.Add(typeof(object).MakeByRefType()); } genericParameters.Add(originalType); string patchName = hasReturnType ? nameof(MethodPatches.ForwardMethodPatch) : nameof(MethodPatches.ForwardMethodPatchVoid); patchParameters.Add(typeof(object)); patchParameters.Add(typeof(MethodInfo)); patchParameters.AddRange(method.GetParameters().Select(p => typeof(object))); genericParameters.AddRange(method.GetParameters().Select(p => p.ParameterType)); if (AccessTools.GetDeclaredMethods(typeof(MethodPatches)).FirstOrDefault(m => m.Name == patchName && m.IsGenericMethod && m.GetParameters().Length == patchParameters.Count) is MethodInfo sMethod) { HarmonyInstance.Patch( original: method, prefix: new HarmonyMethod(sMethod.MakeGenericMethod(genericParameters.ToArray())) ); } } } }
public static void ResolveSyncListFields() { foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) { foreach (var type in assembly.GetTypes()) { if (!typeof(NetworkBehaviour).IsAssignableFrom(type)) { continue; } // execute the static constructor instead of parsing its instructions System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(type.TypeHandle); foreach (var method in AccessTools.GetDeclaredMethods(type)) { if (!method.Name.StartsWith("InvokeSyncList")) { continue; } var methodParams = method.GetParameters(); if (methodParams.Length != 2 || methodParams[0].ParameterType.FullName != "EvoS.Framework.Network.Unity.NetworkBehaviour" || methodParams[1].ParameterType.FullName != "EvoS.Framework.Network.Unity.NetworkReader") { continue; } var methodDelegate = (NetworkBehaviour.CmdDelegate)Delegate.CreateDelegate( typeof(NetworkBehaviour.CmdDelegate), method); var instructions = AnalysisUtils.GetMethodInstructions(method); var hash = 0; foreach (var instruction in instructions) { if (instruction.opcode != OpCodes.Ldfld) { continue; } hash = NetworkBehaviour.GetHashByDelegate(methodDelegate); SyncListLookup.Add(hash, (FieldInfo)instruction.operand); break; } if (hash != 0) { continue; } Log.Print(LogType.Warning, $"No SyncList found in {method.FullDescription()}"); } } } }
static IEnumerable <MethodBase> TargetMethods() { foreach (var m in AccessTools.GetDeclaredMethods(typeof(OverlayDrawer))) { if (m.GetParameters().Length > 0 && m.GetParameters()[0].ParameterType == typeof(Thing)) { yield return(m); } } }
public static IEnumerable <MethodInfo> GetTypeMethods(Type type) { foreach (var method in AccessTools.GetDeclaredMethods(type)) { if (method.DeclaringType == type && !method.IsSpecialName && !method.IsAssembly && method.HasMethodBody()) { yield return(method); } } }
static MethodBase TargetMethod() { MethodInfo methodReloadContent = AccessTools.DeclaredMethod(typeof(ModContentPack), "ReloadContentInt"); if (methodReloadContent != null) { return(methodReloadContent); } return(AccessTools.GetDeclaredMethods(typeof(ModContentPack)).Where(x => x.Name.StartsWith("<ReloadContent>")).FirstOrDefault()); }
static IEnumerable <MethodBase> TargetMethods() { foreach (var m in AccessTools.GetDeclaredMethods(typeof(MirroredBeatmapObjectManager))) { if (m.Name.EndsWith("WasSpawned") || m.Name.EndsWith("WasDespawned")) { yield return(m); } } }
public static IEnumerable <MethodBase> GetTargetMethodsForAssembly(string assemblyName) { Assembly assembly = GetAssemblyByName(assemblyName); if (assembly == null) { Debug.LogError("Failed to find assembly"); } var assemblyTypes = assembly.GetTypes() .Where(type => type.IsClass && !type.Attributes.HasFlag(TypeAttributes.HasSecurity) && !type.Attributes.HasFlag(TypeAttributes.Import) && !type.Attributes.HasFlag(TypeAttributes.Interface) && !type.IsImport && !type.IsInterface && !type.IsSecurityCritical && !BANNED_TYPES.Any(type.FullName.StartsWith) ); var assemblyMethods = assemblyTypes .SelectMany(type => AccessTools.GetDeclaredMethods(type)) .Where(method => { foreach (object attr in method.GetCustomAttributes(false)) { if ((attr is DllImportAttribute) || (attr is MethodImplAttribute) || (attr is CLSCompliantAttribute) || (attr is SecurityCriticalAttribute) || (attr is ObsoleteAttribute) ) { return(false); } } if (method.GetMethodBody() == null || method.Name.Equals("ReadUInt64")) { return(false); } return(!method.ContainsGenericParameters && !method.IsAbstract && !method.IsVirtual && !method.GetMethodImplementationFlags().HasFlag(MethodImplAttributes.Native) && !method.GetMethodImplementationFlags().HasFlag(MethodImplAttributes.Unmanaged) && !method.GetMethodImplementationFlags().HasFlag(MethodImplAttributes.InternalCall) && !method.Attributes.HasFlag(MethodAttributes.PinvokeImpl) && !method.Attributes.HasFlag(MethodAttributes.Abstract) && !method.Attributes.HasFlag(MethodAttributes.UnmanagedExport)); }); return(assemblyMethods.Cast <MethodBase>()); }
protected override MethodBase GetTargetMethod() { // return AccessTools.Method("Diz.Resources.EasyAssets:Init"); easyBundleType = PatcherConstants.TargetAssembly.GetTypes() .Single(type => type.IsClass && type.GetProperty("SameNameAsset") != null); bundlesFieldName = easyBundleType.Name.ToLower() + "_0"; Type targetType = PatcherConstants.TargetAssembly.GetTypes().Single(IsTargetType); return(AccessTools.GetDeclaredMethods(targetType).Single(IsTargetMethod)); }
static MethodBase TargetMethod() { index = DeserializeOrDefault <Dictionary <string, string> >("localeIndex.json"); locale = DeserializeOrDefault <Dictionary <string, string> >(InjectorService.LocaleFile); // Taken from de4dot MethodInfo method = null; foreach (var type in ReflectionHelper.MainModule.GetTypes()) { var fields = AccessTools.GetDeclaredFields(type); var methods = AccessTools.GetDeclaredMethods(type); if (type.IsPublic) { continue; } if (fields.Count != 1) { continue; } if (!fields.Any(field => field.FieldType == typeof(byte[]))) { continue; } if (methods.Count != 1 && methods.Count != 2) { continue; } if (type.GetNestedTypes(AccessTools.all).Length > 0) { continue; } foreach (var m in methods) { var parameters = m.GetParameters(); if (m.ReturnType == typeof(string) && parameters.FirstOrDefault()?.ParameterType == typeof(int)) { method = m; continue; } break; } if (method != null) { break; } } return(method); }
public static List <MethodInfo> InnerMethodsStartingWith(this Type type, string prefix) { var method = GetAllInnerTypes(type) .SelectMany(innerType => AccessTools.GetDeclaredMethods(innerType)) .Where(m => prefix == "*" || m.Name.StartsWith(prefix)) .ToList(); if (method.Count == 0) { throw new Exception("Cannot find method starting with '" + prefix + "' in any inner type of " + type.FullName); } return(method); }
/* todo useful? * /// <summary> * /// Keep Load button in maker character load list enabled if any of the extra toggles are enabled, but none of the stock ones are. * /// </summary> * [HarmonyPrefix] * [HarmonyPatch(typeof(Selectable), "set_interactable")] * public static void LoadButtonOverride(Selectable __instance, ref bool value) * { * if (!value) * { * if (ReferenceEquals(__instance, MakerLoadToggle.LoadButton)) * value = MakerLoadToggle.AnyEnabled; * else if (ReferenceEquals(__instance, MakerCoordinateLoadToggle.LoadButton)) * value = MakerCoordinateLoadToggle.AnyEnabled; * } * }*/ public static void Init() { var hi = BepInEx.Harmony.HarmonyWrapper.PatchAll(typeof(Hooks)); // AI LoadFile(BinaryReader br, int lang, bool noLoadPNG = false, bool noLoadStatus = true) var target = AccessTools.GetDeclaredMethods(typeof(ChaFile)) .Where(x => x.Name == "LoadFile" && x.GetParameters().Any(p => p.ParameterType == typeof(BinaryReader))) .OrderByDescending(x => x.GetParameters().Length) .First(); KoikatuAPI.Logger.LogDebug("Hooking " + target.FullDescription()); hi.Patch(target, new HarmonyMethod(typeof(Hooks), nameof(ChaFileLoadFilePreHook))); }
/********* ** Private methods *********/ /// <summary>Raised after the game is launched, right before the first update tick. This happens once per game session (unrelated to loading saves). All mods are loaded and initialised at this point, so this is a good time to set up mod integrations.</summary> /// <param name="sender">The event sender.</param> /// <param name="e">The event data.</param> private void OnGameLaunched(object sender, GameLaunchedEventArgs e) { var harmony = HarmonyInstance.Create("GZhynko.PufferEggsToMayonnaise.Automate"); if (Helper.ModRegistry.IsLoaded("Pathoschild.Automate")) { harmony.Patch((MethodBase)AccessTools.GetDeclaredMethods(((IEnumerable <Assembly>)AppDomain.CurrentDomain.GetAssemblies()).First <Assembly>((Func <Assembly, bool>)(a => a.FullName.StartsWith("Automate,"))).GetType("Pathoschild.Stardew.Automate.Framework.AutomationFactory")).Find((Predicate <MethodInfo>)(m => ((IEnumerable <ParameterInfo>)m.GetParameters()).Any <ParameterInfo>((Func <ParameterInfo, bool>)(p => p.ParameterType == typeof(StardewValley.Object))))), (HarmonyMethod)null, new HarmonyMethod(typeof(AutomatePatchOverrides), "GetFor", (System.Type[])null), (HarmonyMethod)null); automate = this.Helper.ModRegistry.GetApi <Pathoschild.Stardew.Automate.IAutomateAPI>("Pathoschild.Automate"); automate.AddFactory(new MayonnaiseAutomationFactory()); Monitor.Log("This mod patches Automate. If you encounter any issues using Automate with this mod, try removing it first. If this does help, please report the issue to Pufferfish Chickens mod's page. Thanks!", LogLevel.Debug); } }
static IEnumerable <MethodBase> TargetMethods() { /************* speed limit */ // public bool SetTrafficLight(ushort nodeId, bool flag, ref NetNode node, out ToggleTrafficLightError reason) foreach (var m in AccessTools.GetDeclaredMethods(typeof(TrafficLightManager))) { if (m.Name == nameof(TrafficLightManager.SetTrafficLight) && m.GetParameters().Length == 4 ) { yield return(m); } } }
/// <summary> /// Enables patches depending on various options or other mods. /// </summary> /// <param name="harmony">Our harmony instance.</param> public Cutebold_Patch_HediffRelated(Harmony harmony) { if (Cutebold_Assemblies.CuteboldSettings.eyeAdaptation) { // Allows for dark adaptation, obviously not cave adaptation since that is a different game with cute kobolds. harmony.Patch(AccessTools.Method(typeof(StatPart_Glow), "FactorFromGlow"), postfix: new HarmonyMethod(typeof(Cutebold_Patch_HediffRelated), "CuteboldFactorFromGlowPostfix")); if (Cutebold_Assemblies.CuteboldSettings.darknessOptions != Cutebold_DarknessOptions.IdeologyDefault) { // Ignores the ignoreIfPrefersDarkness flag. harmony.Patch(AccessTools.Method(typeof(StatPart_Glow), "ActiveFor"), postfix: new HarmonyMethod(typeof(Cutebold_Patch_HediffRelated), "CuteboldGlowActiveForPostfix")); } // Applies dark adaptation to all cutebolds as they spawn. harmony.Patch(AccessTools.Method(typeof(Pawn), "SpawnSetup"), postfix: new HarmonyMethod(typeof(Cutebold_Patch_HediffRelated), "CuteboldAdaptationSpawnSetupPostfix")); // Update dark adaptation eye references. harmony.Patch(AccessTools.Method(typeof(HediffSet), "DirtyCache"), postfix: new HarmonyMethod(typeof(Cutebold_Patch_HediffRelated), "CuteboldHediffSetDirtyCachePostfix")); // Update dark adaptation goggle references. harmony.Patch(AccessTools.Method(typeof(Pawn_ApparelTracker), "Notify_ApparelChanged"), postfix: new HarmonyMethod(typeof(Cutebold_Patch_HediffRelated), "CuteboldApparelChangedPostfix")); // 1.1 harmony.Patch(AccessTools.Method(typeof(Pawn_ApparelTracker), "Notify_ApparelAdded"), postfix: new HarmonyMethod(typeof(Cutebold_Patch_HediffRelated), "CuteboldApparelChangedPostfix")); // 1.1 harmony.Patch(AccessTools.Method(typeof(Pawn_ApparelTracker), "Notify_ApparelRemoved"), postfix: new HarmonyMethod(typeof(Cutebold_Patch_HediffRelated), "CuteboldApparelChangedPostfix")); } else { // Removes dark adaptation to all cutebolds as they spawn in. harmony.Patch(AccessTools.Method(typeof(Pawn), "SpawnSetup"), postfix: new HarmonyMethod(typeof(Cutebold_Patch_HediffRelated), "CuteboldNoAdaptationSpawnSetupPostfix")); } // Don't patch if CE is running, we will use that to put goggles below headgear. if (ModLister.GetActiveModWithIdentifier("CETeam.CombatExtended") == null) { // Adjust layer offset for cutebold goggles. //Harmony.DEBUG = true; //Hat rendering was moved to a local function to make things even more fun to patch! MethodInfo toBePatched = AccessTools.GetDeclaredMethods(typeof(PawnRenderer)).ElementAt(29); harmony.Patch(toBePatched, transpiler: new HarmonyMethod(typeof(Cutebold_Patch_HediffRelated), "CuteboldGogglesFixTranspiler")); /* 1.1 harmony.Patch(AccessTools.Method(typeof(PawnRenderer), "RenderPawnInternal", new[] { * typeof(Vector3), * typeof(float), * typeof(bool), * typeof(Rot4), * typeof(Rot4), * typeof(RotDrawMode), * typeof(bool), * typeof(bool), * typeof(bool) * }), transpiler: new HarmonyMethod(typeof(Cutebold_Patch_HediffRelated), "CuteboldRenderPawnInternalTranspiler"));*/ //Harmony.DEBUG = false; } }
private static void PatchAssemblyFull(string key, List <Assembly> assemblies) { var meths = new HashSet <MethodInfo>(); foreach (var asm in assemblies) { try { var asmName = $"{asm.GetName().Name}.dll"; if (patchedAssemblies.Contains(asm.FullName)) { Warn($"patching {asmName} failed, already patched"); continue; } patchedAssemblies.Add(asm.FullName); foreach (var type in AccessTools.GetTypesFromAssembly(asm)) { var methods = AccessTools.GetDeclaredMethods(type).ToList(); foreach (var m in methods) { try { if (ValidMethod(m) && m.DeclaringType == type) { meths.TryAdd(m); } } catch (Exception e) { ReportException(e, $"Skipping method {GetSignature(m)}"); } } } } catch (Exception e) { ReportException(e, $"Failed to patch the assembly {asm.FullName}"); } } var asms = assemblies.Select(a => a.GetName().Name + ".dll").Join(); var asmString = assemblies.Count > 1 ? "assemblies" : "assembly"; Messages.Message($"Attempting to patch {meths.Count} methods from the {asmString} [{asms}]", MessageTypeDefOf.CautionInput, false); MethodTransplanting.UpdateMethods(GUIController.types[key], meths); }
public static IEnumerable <MethodBase> TargetMethods() { Type targetClass = typeof(FoodUtility) .GetNestedTypes(AccessTools.all) .FirstOrDefault(type => type.GetFields(AccessTools.all).Any(field => field.Name == _validatorName)); if (targetClass == null) { return(Enumerable.Empty <MethodBase>()); } _eater = targetClass.GetField("eater", AccessTools.all); return(AccessTools.GetDeclaredMethods(targetClass).Where(m => m.HasMethodBody())); }
public static void PatchGeneratedMethod(this Harmony harmony, Type masterType, Func <MethodInfo, bool> check, HarmonyMethod prefix = null, HarmonyMethod postfix = null, HarmonyMethod transpiler = null) { //Find the compiler-created method nested in masterType that passes the check, Patch it List <Type> nestedTypes = new List <Type>(masterType.GetNestedTypes(BindingFlags.NonPublic)); while (nestedTypes.Any()) { Type type = nestedTypes.Pop(); nestedTypes.AddRange(type.GetNestedTypes(BindingFlags.NonPublic)); foreach (MethodInfo method in AccessTools.GetDeclaredMethods(type).Where(check)) { harmony.Patch(method, prefix, postfix, transpiler); } } }
/// <summary> /// Patches game through Harmony and sets up mod integration. /// </summary> /// <param name="sender"></param> /// <param name="args"></param> private void OnGameLaunched(object sender, GameLaunchedEventArgs args) { HarmonyInstance harmony = HarmonyInstance.Create("JacquePott.MassProduction"); harmony.Patch( original: AccessTools.Method(typeof(SObject), nameof(SObject.performObjectDropInAction)), prefix: new HarmonyMethod(typeof(ObjectOverrides), nameof(ObjectOverrides.PerformObjectDropInAction)) ); harmony.Patch( original: AccessTools.Method(typeof(SObject), nameof(SObject.draw), new Type[] { typeof(SpriteBatch), typeof(int), typeof(int), typeof(float) }), postfix: new HarmonyMethod(typeof(ObjectOverrides), nameof(ObjectOverrides.Draw_Postfix)) ); harmony.Patch( original: AccessTools.Method(typeof(SObject), nameof(SObject.isPlaceable)), postfix: new HarmonyMethod(typeof(ObjectOverrides), nameof(ObjectOverrides.isPlaceable_Postfix)) ); harmony.Patch( original: AccessTools.Method(typeof(SObject), nameof(SObject.performDropDownAction)), prefix: new HarmonyMethod(typeof(ObjectOverrides), nameof(ObjectOverrides.performDropDownAction_Prefix)) ); harmony.Patch( original: AccessTools.Method(typeof(SObject), nameof(SObject.DayUpdate)), prefix: new HarmonyMethod(typeof(ObjectOverrides), nameof(ObjectOverrides.DayUpdate_Prefix)) ); //Automate integration if (Helper.ModRegistry.IsLoaded("Pathoschild.Automate")) { IAutomateAPI automate = Helper.ModRegistry.GetApi <IAutomateAPI>("Pathoschild.Automate"); automate.AddFactory(new MPMAutomationFactory()); Assembly automateAssembly = AppDomain.CurrentDomain.GetAssemblies().First(a => a.FullName.StartsWith("Automate,")); Type automationFactoryType = automateAssembly.GetType("Pathoschild.Stardew.Automate.Framework.AutomationFactory"); MethodInfo methodInfo = AccessTools.GetDeclaredMethods(automationFactoryType).Find(m => m.GetParameters().Any(p => p.ParameterType == typeof(SObject))); harmony.Patch( original: methodInfo, postfix: new HarmonyMethod(typeof(AutomateOverrides), nameof(AutomateOverrides.GetFor)) ); if (Helper.ModRegistry.IsLoaded("Digus.PFMAutomate")) { Monitor.Log("Automate integration for Mass Production clashes with PFMAutomate. Please remove PFMAutomate " + "to have this functionality work correctly.", LogLevel.Warn); } } }
// Adapted from MpUtil.GetLambda static IEnumerable <MethodInfo> GetLambda(Type parentType, string parentMethod = null, MethodType parentMethodType = MethodType.Normal, Type[] parentArgs = null, params int[] lambdaOrdinals) { var parent = GetMethod(parentType, parentMethod, parentMethodType, parentArgs); if (parent == null) { throw new Exception($"Couldn't find parent method ({parentMethodType}) {parentType}::{parentMethod}"); } var parentId = GetMethodDebugId(parent); // Example: <>c__DisplayClass10_ var displayClassPrefix = $"{DisplayClassPrefix}{parentId}_"; foreach (int lambdaOrdinal in lambdaOrdinals) { // Example: <FillTab>b__0 var lambdaNameShort = $"<{parent.Name}>{LambdaMethodInfix}{lambdaOrdinal}"; // Capturing lambda var lambda = parentType.GetNestedTypes(AccessTools.all). Where(t => t.Name.StartsWith(displayClassPrefix)). SelectMany(t => AccessTools.GetDeclaredMethods(t)). FirstOrDefault(m => m.Name == lambdaNameShort); // Example: <FillTab>b__10_0 var lambdaNameFull = $"<{parent.Name}>{LambdaMethodInfix}{parentId}_{lambdaOrdinal}"; // Non-capturing lambda lambda ??= AccessTools.Method(parentType, lambdaNameFull); // Non-capturing cached lambda if (lambda == null && AccessTools.Inner(parentType, SharedDisplayClass) is Type sharedDisplayClass) { lambda = AccessTools.Method(sharedDisplayClass, lambdaNameFull); } if (lambda == null) { throw new Exception($"Couldn't find lambda {lambdaOrdinal} in parent method {parentType}::{parent.Name} (parent method id: {parentId})"); } yield return(lambda); } }