public static SyncDelegate LocalFunc(Type parentType, string parentMethod, string name, Type[] parentArgs = null) { return(Sync.RegisterSyncDelegate( MpMethodUtil.GetLocalFunc(parentType, parentMethod, MethodType.Normal, parentArgs, name), null )); }
public static SyncDelegate Lambda(Type parentType, string parentMethod, int lambdaOrdinal, Type[] parentArgs = null, MethodType parentMethodType = MethodType.Normal) { return(Sync.RegisterSyncDelegate( MpMethodUtil.GetLambda(parentType, parentMethod, parentMethodType, parentArgs, lambdaOrdinal), null )); }
public static SyncDelegate LambdaInGetter(Type parentType, string parentMethod, int lambdaOrdinal) { return(Sync.RegisterSyncDelegate( MpMethodUtil.GetLambda(parentType, parentMethod, MethodType.Getter, null, lambdaOrdinal), null )); }
static MethodBase TargetMethod() { return(MpMethodUtil.GetLocalFunc( typeof(Dialog_BeginRitual), nameof(Dialog_BeginRitual.DoWindowContents), localFunc: "Start" )); }
internal static MethodBase TargetMethod() { var method = MpMethodUtil.GetLambda(typeof(Building_StylingStation), nameof(Building_StylingStation.GetFloatMenuOptions), lambdaOrdinal: 0); stylingStationField = AccessTools.FieldRefAccess <Building_StylingStation>(method.DeclaringType, "<>4__this"); return(method); }
static IEnumerable <MethodBase> TargetMethods() { yield return(AccessTools.Method(typeof(Sustainer), nameof(Sustainer.SustainerUpdate))); yield return(MpMethodUtil.GetLambda(typeof(Sustainer), parentMethodType: MethodType.Constructor, parentArgs: new[] { typeof(SoundDef), typeof(SoundInfo) })); }
static MethodBase TargetMethod() => MpMethodUtil.GetLambda(typeof(Pawn_ApparelTracker), nameof(Pawn_ApparelTracker.SortWornApparelIntoDrawOrder));
static MethodBase TargetMethod() { return(MpMethodUtil.GetLambda(typeof(Archive), nameof(Archive.Add))); }
private static void DoPatches() { bool categoryNeedsAnnouncement = true; string category = null; void SetCategory(string str) { categoryNeedsAnnouncement = true; category = str; } void LogError(string str) { if (categoryNeedsAnnouncement) { Log.Message($"Multiplayer :: {category}"); } Log.Error(str); Multiplayer.loadingErrors = true; } var harmony = Multiplayer.harmony; SetCategory("Annotated patches"); Assembly.GetCallingAssembly().GetTypes().Do(type => { // EarlyPatches are handled in MultiplayerMod.EarlyPatches if (type.IsDefined(typeof(EarlyPatchAttribute))) { return; } try { harmony.CreateClassProcessor(type).Patch(); } catch (Exception e) { LogError($"FAIL: {type} with {e}"); } }); SetCategory("General designation patches"); // General designation handling { var designatorFinalizer = AccessTools.Method(typeof(DesignatorPatches), "DesignateFinalizer"); var designatorMethods = new[] { "DesignateSingleCell", "DesignateMultiCell", "DesignateThing", }; foreach (Type t in typeof(Designator).AllSubtypesAndSelf()) { foreach (string m in designatorMethods) { MethodInfo method = t.GetMethod(m, BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly); if (method == null) { continue; } MethodInfo prefix = AccessTools.Method(typeof(DesignatorPatches), m); try { harmony.PatchMeasure(method, new HarmonyMethod(prefix), null, null, new HarmonyMethod(designatorFinalizer)); } catch (Exception e) { LogError($"FAIL: {t.FullName}:{method.Name} with {e}"); } } } } SetCategory("Non-deterministic patches 1"); // Remove side effects from methods which are non-deterministic during ticking (e.g. camera dependent motes and sound effects) { var randPatchPrefix = new HarmonyMethod(typeof(RandPatches), "Prefix"); var randPatchPostfix = new HarmonyMethod(typeof(RandPatches), "Postfix"); var subSustainerStart = MpMethodUtil.GetLambda(typeof(SubSustainer), parentMethodType: MethodType.Constructor, parentArgs: new[] { typeof(Sustainer), typeof(SubSoundDef) }); var sampleCtor = typeof(Sample).GetConstructor(new[] { typeof(SubSoundDef) }); var subSoundPlay = typeof(SubSoundDef).GetMethod(nameof(SubSoundDef.TryPlay)); var effecterTick = typeof(Effecter).GetMethod(nameof(Effecter.EffectTick)); var effecterTrigger = typeof(Effecter).GetMethod(nameof(Effecter.Trigger)); var effecterCleanup = typeof(Effecter).GetMethod(nameof(Effecter.Cleanup)); var randomBoltMesh = typeof(LightningBoltMeshPool).GetProperty(nameof(LightningBoltMeshPool.RandomBoltMesh)).GetGetMethod(); var drawTrackerCtor = typeof(Pawn_DrawTracker).GetConstructor(new[] { typeof(Pawn) }); var randomHair = typeof(PawnStyleItemChooser).GetMethod(nameof(PawnStyleItemChooser.RandomHairFor)); var effectMethods = new MethodBase[] { subSustainerStart, sampleCtor, subSoundPlay, effecterTick, effecterTrigger, effecterCleanup, randomBoltMesh, drawTrackerCtor, randomHair }; var moteMethods = typeof(MoteMaker).GetMethods(BindingFlags.Static | BindingFlags.Public) .Where(m => m.Name != "MakeBombardmentMote"); // Special case, just calls MakeBombardmentMote_NewTmp, prevents Hugslib complains var fleckMethods = typeof(FleckMaker).GetMethods(BindingFlags.Static | BindingFlags.Public) .Where(m => m.ReturnType == typeof(void)); foreach (MethodBase m in effectMethods.Concat(moteMethods).Concat(fleckMethods)) { try { harmony.PatchMeasure(m, randPatchPrefix, randPatchPostfix); } catch (Exception e) { LogError($"FAIL: {m.DeclaringType.FullName}:{m.Name} with {e}"); } } } SetCategory("Non-deterministic patches 2"); // Set ThingContext and FactionContext (for pawns and buildings) in common Thing methods { var thingMethodPrefix = new HarmonyMethod(typeof(ThingMethodPatches).GetMethod("Prefix")); var thingMethodPostfix = new HarmonyMethod(typeof(ThingMethodPatches).GetMethod("Postfix")); var thingMethods = new[] { "Tick", "TickRare", "TickLong", "SpawnSetup", "TakeDamage", "Kill" }; foreach (Type t in typeof(Thing).AllSubtypesAndSelf()) { foreach (string m in thingMethods) { MethodInfo method = t.GetMethod(m, BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly); if (method != null) { try { harmony.PatchMeasure(method, thingMethodPrefix, thingMethodPostfix); } catch (Exception e) { LogError($"FAIL: {method.DeclaringType.FullName}:{method.Name} with {e}"); } } } } } // Full precision floating point saving { var doubleSavePrefix = new HarmonyMethod(typeof(ValueSavePatch).GetMethod(nameof(ValueSavePatch.DoubleSave_Prefix))); var floatSavePrefix = new HarmonyMethod(typeof(ValueSavePatch).GetMethod(nameof(ValueSavePatch.FloatSave_Prefix))); var valueSaveMethod = typeof(Scribe_Values).GetMethod(nameof(Scribe_Values.Look)); harmony.PatchMeasure(valueSaveMethod.MakeGenericMethod(typeof(double)), doubleSavePrefix, null); harmony.PatchMeasure(valueSaveMethod.MakeGenericMethod(typeof(float)), floatSavePrefix, null); } SetCategory("Map time gui patches"); // Set the map time for GUI methods depending on it { var setMapTimePrefix = new HarmonyMethod(AccessTools.Method(typeof(SetMapTimeForUI), "Prefix")); var setMapTimePostfix = new HarmonyMethod(AccessTools.Method(typeof(SetMapTimeForUI), "Postfix")); var windowMethods = new[] { "DoWindowContents", "WindowUpdate" }; foreach (string m in windowMethods) { harmony.PatchMeasure(typeof(MainTabWindow_Inspect).GetMethod(m), setMapTimePrefix, setMapTimePostfix); } foreach (var t in typeof(InspectTabBase).AllSubtypesAndSelf()) { var method = t.GetMethod("FillTab", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.DeclaredOnly); if (method != null && !method.IsAbstract) { try { harmony.PatchMeasure(method, setMapTimePrefix, setMapTimePostfix); } catch (Exception e) { LogError($"FAIL: {method.DeclaringType.FullName}:{method.Name} with {e}"); } } } } SetCategory(""); }
static IEnumerable <MethodBase> TargetMethods() { yield return(MpMethodUtil.GetLambda(typeof(Dialog_Trade), nameof(Dialog_Trade.DoWindowContents))); yield return(MpMethodUtil.GetLambda(typeof(Dialog_Trade), nameof(Dialog_Trade.DoWindowContents))); }