public static void TryRegister() { if (!Instance.IsActive) { return; } try { if (!Instance.GetField <bool>("enabled")) { return; } var registerSyncMethod = AccessTools.FirstMethod(Instance.Integrator, method => method.Name == "RegisterSyncMethod" && method.GetParameters()[0].ParameterType == typeof(Type)); registerSyncMethod.Invoke(Instance.MainAssembly, new object[] { typeof(Mod_Multiplayer), nameof(SetSelfTend), null }); registerSyncMethod.Invoke(Instance.MainAssembly, new object[] { typeof(Mod_Multiplayer), nameof(SetFoodRestriction), null }); registerSyncMethod.Invoke(Instance.MainAssembly, new object[] { typeof(Mod_Multiplayer), nameof(SetAssignment), null }); registerSyncMethod.Invoke(Instance.MainAssembly, new object[] { typeof(Mod_Multiplayer), nameof(SetArea), null }); registerSyncMethod.Invoke(Instance.MainAssembly, new object[] { typeof(Mod_Multiplayer), nameof(SetOutfit), null }); Mod.Log("Multiplayer ready with API " + Instance.GetField <string>("API")); } catch (Exception exception) { Instance.FailInitialization(exception); } }
public static MethodBase TargetMethod() { var type = AccessTools.FirstInner(typeof(PotionDropControl), t => t.Name.Contains("<RefinePotion>d__21")); LogF($"TargetMethod {type}"); return(AccessTools.FirstMethod(type, method => method.Name.Contains("MoveNext"))); }
private static IEnumerable <CodeInstruction> Transpiler(IEnumerable <CodeInstruction> instructions) { foreach (CodeInstruction instruction in instructions) { if (instruction.opcode == OpCodes.Call) { if (instruction.operand != null && instruction.operand is MethodBase methodBase && methodBase.Name != nameof(RoundSummary._ProcessServerSideCode)) { yield return(instruction); } else { yield return(new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(RoundEnd), nameof(Process)))); yield return(new CodeInstruction(OpCodes.Ldarg_0)); yield return(new CodeInstruction(OpCodes.Call, AccessTools.FirstMethod(typeof(MECExtensionMethods2), (m) => { var generics = m.GetGenericArguments(); var paramseters = m.GetParameters(); return m.Name == "CancelWith" && generics.Length == 1 && paramseters.Length == 2 && paramseters[0].ParameterType == typeof(IEnumerator <float>) && paramseters[1].ParameterType == generics[0]; }).MakeGenericMethod(typeof(RoundSummary)))); } }
static Garam_RaceAddon() { var harmony = new Harmony("com.rimworld.Dalrae.Garam_RaceAddon"); harmony.PatchAll(); harmony.Patch(AccessTools.FirstMethod(AccessTools.FirstInner(typeof(CharacterCardUtility), x => x.Name.Contains("14_1")), x => x.Name.Contains("b__23")), null, null, new HarmonyMethod(typeof(HarmonyPathces_DrawCharacterCard), "Transpiler")); //==================== Recipe Import ====================// foreach (var thingDef in DefDatabase <RaceAddonThingDef> .AllDefs) { if (thingDef.raceAddonSettings.basicSetting.humanRecipeImport) { ThingDef human = DefDatabase <ThingDef> .AllDefs.First((ThingDef def) => def.defName == "Human"); foreach (RecipeDef recipe in human.AllRecipes) { if (!recipe.targetsBodyPart || recipe.appliedOnFixedBodyParts.NullOrEmpty() || recipe.appliedOnFixedBodyParts.Any((BodyPartDef def) => thingDef.race.body.AllParts.Any((BodyPartRecord bpr) => bpr.def == def))) { if (!thingDef.recipes.Contains(recipe)) { thingDef.recipes.Add(recipe); } } } } } }
static Mod() { Harmony harmony = new Harmony("com.rimworld.Dalrae.Garam_RaceAddon"); harmony.PatchAll(); harmony.Patch(AccessTools.FirstMethod(AccessTools.FirstInner(typeof(CharacterCardUtility), x => x.Name.Contains("14_1")), x => x.Name.Contains("b__21")), null, null, new HarmonyMethod(typeof(DrawCharacterCard), "Transpiler")); foreach (var type in typeof(WorkGiver).AllSubclasses()) { if (AccessTools.DeclaredMethod(type, "ShouldSkip") is var methodInfo && methodInfo != null) { harmony.Patch(methodInfo, null, new HarmonyMethod(typeof(ShouldSkip), "Postfix"), null, null); } } foreach (var thingDef in DefDatabase <RaceAddonThingDef> .AllDefsListForReading) { if (thingDef.raceAddonSettings.basicSetting.recipeImportTarget != null) { // Recipe Import ThingDef targetThingDef = DefDatabase <ThingDef> .AllDefs.First((ThingDef def) => def == thingDef.raceAddonSettings.basicSetting.recipeImportTarget); thingDef.recipes = thingDef.recipes ?? new List <RecipeDef>(); foreach (RecipeDef recipe in targetThingDef.AllRecipes) { if (RecipeImport(recipe, thingDef.race.body)) { thingDef.recipes.AddDistinct(recipe); } } } } foreach (var customPawnKindDef in DefDatabase <CustomPawnKindDef> .AllDefsListForReading) { foreach (var setting in customPawnKindDef.pawnKindDefReplaceSettings) { if (!RaceAddon.PawnKindDefReplaceSettings.ContainsKey(setting.originalPawnKindDef)) { RaceAddon.PawnKindDefReplaceSettings.Add(setting.originalPawnKindDef, new List <Pair <PawnKindDef, float> >()); } if (RaceAddon.PawnKindDefReplaceSettings[setting.originalPawnKindDef].Count > 0) { for (int i = 0; i < RaceAddon.PawnKindDefReplaceSettings[setting.originalPawnKindDef].Count; i++) { if (setting.originalWeight < RaceAddon.PawnKindDefReplaceSettings[setting.originalPawnKindDef][i].Second) { RaceAddon.PawnKindDefReplaceSettings[setting.originalPawnKindDef][i] = new Pair <PawnKindDef, float>(setting.originalPawnKindDef, setting.originalWeight); } } } else { RaceAddon.PawnKindDefReplaceSettings[setting.originalPawnKindDef].Add(new Pair <PawnKindDef, float>(setting.originalPawnKindDef, setting.originalWeight)); } RaceAddon.PawnKindDefReplaceSettings[setting.originalPawnKindDef].Add(new Pair <PawnKindDef, float>(setting.replacedPawnKindDef, setting.replacedWeight)); } } }
// here, inside the patch class, you can place the auxilary patch methods // for example TargetMethod: public MethodBase TargetMethod() { // use normal reflection or helper methods in <AccessTools> to find the method/constructor // you want to patch and return its MethodInfo/ConstructorInfo // var type = AccessTools.FirstInner(typeof(TheClass), t => t.Name.Contains("Stuff")); return(AccessTools.FirstMethod(type, method => method.Name.Contains("SomeMethod"))); }
internal static IEnumerable <CodeInstruction> Transpiler(IEnumerable <CodeInstruction> instrs, ILGenerator il) { MethodInfo LPayAttention = AccessTools.Method(typeof(JobDriver_PayAttention), nameof(JobDriver_PayAttention.ForcePayAttention)); FieldInfo Ltoil = AccessTools.Field(dc19_0, "toil"); MethodInfo Lget_CurJob = AccessTools.Method(typeof(Pawn), "get_CurJob"); FieldInfo LtameeInd = AccessTools.Field(dc19_0, "tameeInd"); MethodInfo LGetActor = AccessTools.Method(typeof(Toil), nameof(Toil.GetActor)); MethodInfo LGetTarget = AccessTools.Method(typeof(Job), nameof(Job.GetTarget)); MethodInfo Lop_Explicit = AccessTools.FirstMethod(typeof(LocalTargetInfo), m => m.Name == "op_Explicit" && m.ReturnType == typeof(Thing)); yield return(new CodeInstruction(OpCodes.Ldarg_0)); yield return(new CodeInstruction(OpCodes.Ldfld, Ltoil)); yield return(new CodeInstruction(OpCodes.Callvirt, LGetActor)); yield return(new CodeInstruction(OpCodes.Stloc_0)); yield return(new CodeInstruction(OpCodes.Ldloc_0)); yield return(new CodeInstruction(OpCodes.Callvirt, Lget_CurJob)); yield return(new CodeInstruction(OpCodes.Ldarg_0)); yield return(new CodeInstruction(OpCodes.Ldfld, LtameeInd)); yield return(new CodeInstruction(OpCodes.Callvirt, LGetTarget)); yield return(new CodeInstruction(OpCodes.Call, Lop_Explicit)); yield return(new CodeInstruction(OpCodes.Castclass, typeof(Pawn))); yield return(new CodeInstruction(OpCodes.Ldc_I4, 270)); yield return(new CodeInstruction(OpCodes.Ldloc_0)); yield return(new CodeInstruction(OpCodes.Ldc_I4_0)); yield return(new CodeInstruction(OpCodes.Call, LPayAttention)); foreach (var i in instrs) { yield return(i); } }
public static IEnumerable <CodeInstruction> draw_Transpiler(IEnumerable <CodeInstruction> instructions, ILGenerator generator) { LinkedList <CodeInstruction> newInstructions = new LinkedList <CodeInstruction>(instructions); CodeInstruction codeInstruction = newInstructions.FirstOrDefault(c => c.opcode == OpCodes.Call && c.operand?.ToString() == "Microsoft.Xna.Framework.Vector2 getScale()"); LinkedListNode <CodeInstruction> linkedListNode = newInstructions.Find(codeInstruction); if (linkedListNode != null && codeInstruction != null) { linkedListNode.Value = new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(ObjectOverrides), "getScale", new Type[] { typeof(Object) })); } codeInstruction = newInstructions.FirstOrDefault(c => c.opcode == OpCodes.Callvirt && c.operand?.ToString() == "Void Draw(Microsoft.Xna.Framework.Graphics.Texture2D, Microsoft.Xna.Framework.Rectangle, System.Nullable`1[Microsoft.Xna.Framework.Rectangle], Microsoft.Xna.Framework.Color, Single, Microsoft.Xna.Framework.Vector2, Microsoft.Xna.Framework.Graphics.SpriteEffects, Single)"); linkedListNode = newInstructions.Find(codeInstruction); if (linkedListNode != null && codeInstruction != null) { newInstructions.AddBefore(linkedListNode, new CodeInstruction(OpCodes.Ldarg_0, null)); linkedListNode.Value = new CodeInstruction(OpCodes.Call, AccessTools.FirstMethod(typeof(ObjectOverrides), m => m.Name == "DrawAnimation")); } return(newInstructions); }
public static MethodInfo TargetMethod() => // "IsEdificeOverNonEdifice" Isn't compiled away? Okay I'll use that AccessTools.FirstMethod(typeof(GenConstruct), method => method.Name.Contains("IsEdificeOverNonEdifice"));
public static MethodInfo TargetMethod() { var type = AccessTools.FirstInner(typeof(DebugToolsSpawning), t => t.Name.Contains("DisplayClass1_0")); return(AccessTools.FirstMethod(type, method => method.Name.Contains("SpawnPawn"))); }
public void InitializeSingletons(Type wrapperType, ManualLogSource logger) { var fieldsSeen = new HashSet <FieldInfo>(); var propertiesSeen = new HashSet <PropertyInfo>(); var methodsSeen = new HashSet <MethodInfo>(); var constructorsSeen = new HashSet <ConstructorInfo>(); var staticFieldRefAccessMethod = AccessTools.FirstMethod(typeof(AccessTools), f => f.Name == nameof(AccessTools.StaticFieldRefAccess) && f.GetParameters().Length == 1 && f.GetParameters().Single().ParameterType == typeof(FieldInfo) && f.ContainsGenericParameters && f.GetGenericArguments().Length == 1); var fieldRefAccessMethod = AccessTools.Method(typeof(AccessTools), nameof(AccessTools.FieldRefAccess), new Type[] { typeof(FieldInfo) }); foreach (var field in wrapperType.GetFields(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)) { if (field.FieldType.IsGenericType && (typeof(AccessTools.FieldRef <object, object>).GetGenericTypeDefinition() == field.FieldType.GetGenericTypeDefinition() || typeof(AccessTools.FieldRef <object>).GetGenericTypeDefinition() == field.FieldType.GetGenericTypeDefinition()) && field.GetValue(null) == null) { var wrapperMember = field.GetCustomAttribute <WrapperField>(); if (wrapperMember != null) { var fieldInfo = WrappedType.GetField(wrapperMember.ObfuscatedName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (fieldInfo != null) { if (field.FieldType.GenericTypeArguments.Length == 1) { //TODO: Figure out how to do statics. field.SetValue(null, staticFieldRefAccessMethod.MakeGenericMethod(field.FieldType.GenericTypeArguments).Invoke(null, new object[] { fieldInfo })); } else if (field.FieldType.GenericTypeArguments.Length == 2) { field.SetValue(null, fieldRefAccessMethod.MakeGenericMethod(field.FieldType.GenericTypeArguments).Invoke(null, new object[] { fieldInfo })); } else { logger.LogError($"Field {wrapperType.Name}.{field.Name} has an incorrect number of generic arguments! Panic!"); Environment.Exit(1); } fieldsSeen.Add(fieldInfo); logger.LogDebug($"Loaded field {wrapperType.Name}.{field.Name}"); } } } else if (field.FieldType == typeof(FieldInfo) && field.GetValue(null) == null) { var wrapperMember = field.GetCustomAttribute <WrapperField>(); if (wrapperMember != null) { var fieldInfo = WrappedType.GetField(wrapperMember.ObfuscatedName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (fieldInfo != null) { field.SetValue(null, fieldInfo); fieldsSeen.Add(fieldInfo); logger.LogDebug($"Loaded field {wrapperType.Name}.{field.Name}"); #if DEBUG if (!fieldInfo.IsStatic) { logger.LogWarning($"This is a FieldInfo field, please replace it with a FieldRefAccess version!"); } #endif } } } else if (field.FieldType == typeof(PropertyInfo) && field.GetValue(null) == null) { var wrapperProperty = field.GetCustomAttribute <WrapperProperty>(); if (wrapperProperty != null) { var propertyInfo = WrappedType.GetProperty(wrapperProperty.ObfuscatedName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (propertyInfo != null) { field.SetValue(null, propertyInfo); propertiesSeen.Add(propertyInfo); logger.LogDebug($"Loaded property {wrapperType.Name}.{field.Name}"); } } } else if (field.FieldType == typeof(FastInvokeHandler) && field.GetValue(null) == null) { var wrapperMethod = field.GetCustomAttribute <WrapperMethod>(); if (wrapperMethod != null) { var methodInfo = wrapperMethod.GetMethodInfo(WrappedType); if (methodInfo != null) { field.SetValue(null, MethodInvoker.GetHandler(methodInfo)); methodsSeen.Add(methodInfo); logger.LogDebug($"Loaded method {wrapperType.Name}.{field.Name}"); } } } else if (field.FieldType == typeof(ConstructorInfo) && field.GetValue(null) == null) { var wrapperConstructor = field.GetCustomAttribute <WrapperConstructor>(); if (wrapperConstructor != null) { var constructorInfo = WrappedType.GetConstructor(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, wrapperConstructor.Types, null); if (constructorInfo != null) { field.SetValue(null, constructorInfo); constructorsSeen.Add(constructorInfo); logger.LogDebug($"Loaded constructor {wrapperType.Name}.{field.Name}"); } } } if ((field.FieldType == typeof(FieldInfo) || (field.FieldType.IsGenericType && field.FieldType.GetGenericTypeDefinition() == typeof(AccessTools.FieldRef <,>)) || field.FieldType == typeof(PropertyInfo) || field.FieldType == typeof(MethodInfo) || field.FieldType == typeof(FastInvokeHandler) || field.FieldType == typeof(ConstructorInfo)) && field.GetValue(null) == null) { logger.LogError($"Uh oh! {wrapperType.Name}.{field.Name} was null!"); #if DEBUG logger.LogError($"Program terminating until this wrapper is fixed!"); Environment.Exit(1); #endif } } #if DEBUG var remainingFields = WrappedType.GetFields(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly).Except(fieldsSeen).ToList(); var remainingProperties = WrappedType.GetProperties(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly).Except(propertiesSeen).ToList(); var remainingMethods = WrappedType.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly).Except(methodsSeen).ToList(); var remainingConstructors = WrappedType.GetConstructors(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly).Except(constructorsSeen).ToList(); if (remainingFields.Count > 0) { logger.LogWarning($"Wrapper {wrapperType.Name} is missing {remainingFields.Count} fields, first is {remainingFields.First().Name.DecodeUnicode()}."); } if (remainingProperties.Count > 0) { logger.LogWarning($"Wrapper {wrapperType.Name} is missing {remainingProperties.Count} properties, first is {remainingProperties.First().Name.DecodeUnicode()}."); } if (remainingMethods.Count > 0) { logger.LogWarning($"Wrapper {wrapperType.Name} is missing {remainingMethods.Count} methods (unless there's method duplication), first is {remainingMethods.First().Name.DecodeUnicode()}."); } if (remainingConstructors.Count > 0) { logger.LogWarning($"Wrapper {wrapperType.Name} is missing {remainingConstructors.Count} constructors, first is {remainingConstructors.First().Name.DecodeUnicode()}."); } if (remainingFields.Count == 0 && remainingProperties.Count == 0 && remainingMethods.Count == 0 && remainingConstructors.Count == 0) { logger.LogDebug($"Wrapper {wrapperType.Name} is fully defined."); } #endif }
private static MethodBase GetSandboxMethod(Type typ) => AccessTools.FirstMethod(typ, info => info.IsAssembly && info.ReturnType == typeof(void) && info.GetParameters().FirstOrDefault()?.ParameterType.Name == "TypeDefinition");