public AlphaBehavioursAndEvents(ModContentPack mod) { //RNG Fix { var rngFixConstructors = new[] { "AlphaBehavioursAndEvents.DeathActionWorker_ExplodeAndSpawnEggs", "AlphaBehavioursAndEvents.Hediff_Crushing", // Ocular plant conversion "AlphaBehavioursAndEvents.CompAbilityOcularConversion", "AlphaBehavioursAndEvents.Gas_Ocular", }; PatchingUtilities.PatchSystemRandCtor(rngFixConstructors, false); var rngFixMethods = new[] //System.Random fixes { "AlphaBehavioursAndEvents.Hediff_Crushing:RandomFilthGenerator", // Ocular plant conversion "AlphaBehavioursAndEvents.CompAbilityOcularConversion:Apply", "AlphaBehavioursAndEvents.Gas_Ocular:Tick", }; PatchingUtilities.PatchPushPopRand(rngFixMethods); } }
public VEE(ModContentPack mod) { var methodsForAll = new[] { "VEE.HeddifComp_MightJoin:CompPostTick", "VEE.HuntingParty:TryExecuteWorker", // These 4 methods initialize System.Random, but don't use them in any way whatsoever. //"VEE.PurpleEvents.GlobalWarming:ChangeBiomes", //"VEE.PurpleEvents.GlobalWarming:ChangeTileTemp", //"VEE.PurpleEvents.IceAge:ChangeBiomes", //"VEE.PurpleEvents.IceAge:ChangeTileTemp", "VEE.PurpleEvents.PsychicBloom:Init", "VEE.RegularEvents.ApparelPod:TryExecuteWorker", "VEE.RegularEvents.CaravanAnimalWI:GenerateGroup", "VEE.RegularEvents.MeteoriteShower:TryExecuteWorker", "VEE.RegularEvents.WeaponPod:TryExecuteWorker", }; PatchingUtilities.PatchSystemRand(methodsForAll, false); // This method only calls other methods that use RNG calls PatchingUtilities.PatchPushPopRand("VEE.RegularEvents.EarthQuake:TryExecuteWorker"); // Only patch System.Random out, as this methods is only called by other ones PatchingUtilities.PatchSystemRand("VEE.RegularEvents.EarthQuake:DamageInRadius", false); // Unity RNG PatchingUtilities.PatchUnityRand("VEE.Shuttle:Tick"); LongEventHandler.ExecuteWhenFinished(LatePatch); }
static void LateSyncMethods() { // Artillery fix { var type = AccessTools.TypeByName("VFESecurity.CompLongRangeArtillery"); selectedCompsProperty = AccessTools.Property(type, "SelectedComps"); turretProperty = AccessTools.Property(type, "Turret"); targetedTileField = AccessTools.Field(type, "targetedTile"); resetWarmupTicksMethod = AccessTools.DeclaredMethod(type, "ResetWarmupTicks"); MP.RegisterSyncMethod(type, "ResetForcedTarget"); MP.RegisterSyncMethod(typeof(VFESecurity), nameof(SetTargetedTile)); MpCompat.harmony.Patch(AccessTools.Method(type, "SetTargetedTile"), new HarmonyMethod(typeof(VFESecurity), nameof(Prefix))); } // RNG fix { var methods = new[] { // ArtilleryComp:TryResolveArtilleryCount is called by ArtilleryComp:CompTick "VFESecurity.ArtilleryComp:BombardmentTick", "VFESecurity.ArtilleryComp:TryStartBombardment", "VFESecurity.Building_Shield:Notify_EnergyDepleted", "VFESecurity.Building_Shield:Draw", "VFESecurity.CompLongRangeArtillery:CompTick", }; PatchingUtilities.PatchPushPopRand(AccessTools.Method("VFESecurity.Building_Shield:AbsorbDamage", new Type[] { typeof(float), typeof(DamageDef), typeof(float) })); PatchingUtilities.PatchPushPopRand(methods); } }
public VEE(ModContentPack mod) { var methodsForAll = new[] { "VEE.DummySpaceBattle:Tick", "VEE.HeddifComp_MightJoin:CompPostTick", "VEE.Shuttle:Tick", // These 4 methods initialize System.Random, but don't use them in any way whatsoever. //"VEE.PurpleEvents.GlobalWarming:ChangeBiomes", //"VEE.PurpleEvents.GlobalWarming:ChangeTileTemp", //"VEE.PurpleEvents.IceAge:ChangeBiomes", //"VEE.PurpleEvents.IceAge:ChangeTileTemp", "VEE.PurpleEvents.PsychicBloom:Init", "VEE.RegularEvents.ApparelPod:TryExecuteWorker", "VEE.RegularEvents.CaravanAnimalWI:GenerateGroup", "VEE.RegularEvents.Drought:HarmPlant", "VEE.RegularEvents.HuntingParty:TryExecuteWorker", "VEE.RegularEvents.MeteoriteShower:TryExecuteWorker", "VEE.RegularEvents.SpaceBattle:GameConditionTick", // This method was having issues with transpiling no matter what I did, skipping it until it can be fixed "VEE.RegularEvents.WeaponPod:TryExecuteWorker", }; PatchingUtilities.PatchSystemRand(methodsForAll, false); // This method only calls other methods that use RNG calls PatchingUtilities.PatchPushPopRand("VEE.RegularEvents.EarthQuake:TryExecuteWorker"); // Only patch System.Random out, as this methods is only called by other ones PatchingUtilities.PatchSystemRand("VEE.RegularEvents.EarthQuake:DamageInRadius", false); }
public AlphaBehavioursAndEvents(ModContentPack mod) { //RNG Fix { var rngFixConstructors = new[] { "AlphaBehavioursAndEvents.CompAnimalProduct", "AlphaBehavioursAndEvents.CompExploder", "AlphaBehavioursAndEvents.CompGasProducer", "AlphaBehavioursAndEvents.CompInitialHediff", "AlphaBehavioursAndEvents.Gas_Ocular", "AlphaBehavioursAndEvents.Hediff_Crushing", //"NewAlphaAnimalSubproducts.CompAnimalProduct ", // System.Random initialized, but not used }; PatchingUtilities.PatchSystemRandCtor(rngFixConstructors, false); var rngFixMethods = new[] //System.Random fixes { "AlphaBehavioursAndEvents.CompGasProducer:CompTick", "AlphaBehavioursAndEvents.CompAnimalProduct:InformGathered", "AlphaBehavioursAndEvents.CompInitialHediff:CompTickRare", "AlphaBehavioursAndEvents.Gas_Ocular:Tick", "AlphaBehavioursAndEvents.Hediff_Crushing:RandomFilthGenerator", "AlphaBehavioursAndEvents.CompExploder:wickInitializer", }; PatchingUtilities.PatchPushPopRand(rngFixMethods); PatchingUtilities.PatchSystemRand("AlphaBehavioursAndEvents.DamageWorker_ExtraInfecter:ApplySpecialEffectsToPart"); } }
public VFESecurity(ModContentPack mod) { // RNG fix { var methodNames = new[] { "VFESecurity.ArtilleryStrikeArrivalAction_AIBase:Arrived", "VFESecurity.ArtilleryStrikeArrivalAction_Insectoid:StrikeAction", "VFESecurity.ArtilleryStrikeArrivalAction_Map:Arrived", "VFESecurity.ArtilleryStrikeArrivalAction_Outpost:StrikeAction", "VFESecurity.ArtilleryStrikeArrivalAction_PeaceTalks:Arrived", "VFESecurity.ArtilleryStrikeArrivalAction_Settlement:StrikeAction", "VFESecurity.WorldObjectCompProperties_Artillery:ArtilleryCountFor", // ArtilleryStrikeUtility:GetRandomShellFor and ArtilleryStrikeUtility:PotentialStrikeCells are only called by methods that are patched already "VFESecurity.Building_BarbedWire:SpringSub", "VFESecurity.Building_TrapBear:SpringSub", // This one seems like it should have no random calls at all in its hierarchy, but desync traces show that there are actually some. "VFESecurity.Verb_Dazzle:TryCastShot", "NoCamShakeExplosions.DamageWorker_FlameNoCamShake:Apply", "NoCamShakeExplosions.DamageWorker_FlameNoCamShake:ExplosionAffectCell", // Motes "VFESecurity.ExtendedMoteMaker:SearchlightEffect", }; PatchingUtilities.PatchPushPopRand(AccessTools.Method(AccessTools.Inner(AccessTools.TypeByName("VFESecurity.Patch_Building_Trap"), "Spring"), "ShouldDestroy")); PatchingUtilities.PatchPushPopRand(methodNames); LongEventHandler.ExecuteWhenFinished(LateSyncMethods); } }
public VFEF(ModContentPack mod) { //RNG Fix { var methods = new[] { "VFEF.MoteSprinkler:NewMote", "VFEF.MoteSprinkler:ThrowWaterSpray", }; PatchingUtilities.PatchPushPopRand(methods); } }
public Desynchronized(ModContentPack mod) { var rngFixMethods = new[] { "Desynchronized.TNDBS.Pawn_NewsKnowledgeTracker:ForgetRandom", "Desynchronized.TNDBS.Pawn_NewsKnowledgeTracker:ForgetRandomly", "Desynchronized.TNDBS.Utilities.NewsSpreadUtility:SelectNewsRandomly", "Desynchronized.TNDBS.Utilities.NewsSpreadUtility:SelectNewsDistinctly", "Desynchronized.Patches.NewsTransmit.PostFix_InteractionWorker:ExecuteNewsTarnsmission", "Desynchronized.TNDBS.TaleNewsPawnDied:CalculateNewsImportanceForPawn", }; PatchingUtilities.PatchPushPopRand(rngFixMethods); }
public ExplosiveTrailsEffect(ModContentPack mod) { if (isApplied) { return; } isApplied = true; var methodNames = new[] { "ExplosiveTrailsEffect.ExhaustFlames:ThrowRocketExhaustFlame", "ExplosiveTrailsEffect.SmokeThrowher:ThrowSmokeTrail", }; PatchingUtilities.PatchPushPopRand(methodNames); }
public VanillaExpandedFramework(ModContentPack mod) { var type = AccessTools.TypeByName("ItemProcessor.Building_ItemProcessor"); // _1, _5 and _7 are used to check if gizmo should be enabled, so we don't sync them MpCompat.RegisterSyncMethodsByIndex(type, "<GetGizmos>", 0, 2, 3, 4, 6, 8, 9, 10); type = AccessTools.TypeByName("ItemProcessor.Command_SetQualityList"); MP.RegisterSyncWorker <Command>(SyncCommandWithBuilding, type, shouldConstruct: true); MpCompat.RegisterSyncMethodsByIndex(type, "<ProcessInput>", Enumerable.Range(0, 8).ToArray()); type = AccessTools.TypeByName("ItemProcessor.Command_SetOutputList"); MP.RegisterSyncWorker <Command>(SyncCommandWithBuilding, type, shouldConstruct: true); MP.RegisterSyncMethod(type, "TryConfigureIngredientsByOutput"); // Keep an eye on this in the future, seems like something the devs could combine into a single class at some point foreach (var ingredientNumber in new[] { "First", "Second", "Third", "Fourth" }) { type = AccessTools.TypeByName($"ItemProcessor.Command_Set{ingredientNumber}ItemList"); MP.RegisterSyncWorker <Command>(SyncSetIngredientCommand, type, shouldConstruct: true); MP.RegisterSyncMethod(type, $"TryInsert{ingredientNumber}Thing"); MpCompat.RegisterSyncMethodsByIndex(type, "<ProcessInput>", 0); } // AddHediff desyncs with Arbiter, but seems fine without it PatchingUtilities.PatchPushPopRand("VanillaCookingExpanded.Thought_Hediff:MoodOffset"); type = AccessTools.TypeByName("VFECore.CompPawnDependsOn"); MpCompat.RegisterSyncMethodByIndex(type, "<CompGetGizmosExtra>", 0).SetDebugOnly(); type = AccessTools.TypeByName("VanillaFurnitureExpanded.CompConfigurableSpawner"); MpCompat.RegisterSyncMethodByIndex(type, "<CompGetGizmosExtra>", 0).SetDebugOnly(); type = AccessTools.TypeByName("VanillaFurnitureExpanded.Command_SetItemsToSpawn"); MP.RegisterSyncDelegate(type, "<>c__DisplayClass2_0", "<ProcessInput>b__1"); type = AccessTools.TypeByName("VanillaFurnitureExpanded.CompRockSpawner"); MpCompat.RegisterSyncMethodByIndex(type, "<CompGetGizmosExtra>", 0); type = AccessTools.TypeByName("VanillaFurnitureExpanded.Command_SetStoneType"); setStoneBuildingField = AccessTools.Field(type, "building"); MpCompat.RegisterSyncMethodByIndex(type, "<ProcessInput>", 0); MP.RegisterSyncWorker <Command>(SyncSetStoneTypeCommand, type, shouldConstruct: true); MP.RegisterSyncDelegate(type, "<>c__DisplayClass2_0", "<ProcessInput>b__1"); }
public VFEF(ModContentPack mod) { //RNG Fix { var methods = new[] { "VFEF.MoteSprinkler:NewMote", "VFEF.MoteSprinkler:ThrowWaterSpray", }; PatchingUtilities.PatchPushPopRand(methods); } // Gizmo fix { // Toggle should scarecrow affect tamed/player animals MpCompat.RegisterLambdaMethod("VFEF.Building_Scarecrow", "GetGizmos", 1); } }
public VanillaFishingExpanded(ModContentPack mod) { // RNG fix { PatchingUtilities.PatchSystemRandCtor("VCE_Fishing.JobDriver_Fish", false); PatchingUtilities.PatchPushPopRand("VCE_Fishing.JobDriver_Fish:SelectFishToCatch"); } // Gizmo (select fish size to catch) { commandType = AccessTools.TypeByName("VCE_Fishing.Command_SetFishList"); mapField = AccessTools.Field(commandType, "map"); fishingZoneField = AccessTools.Field(commandType, "zone"); MpCompat.RegisterSyncMethodsByIndex(commandType, "<ProcessInput>", Enumerable.Range(0, 3).ToArray()); MP.RegisterSyncWorker <Command>(SyncFishingZoneChange, commandType, shouldConstruct: false); } }
public AlphaBiomes(ModContentPack mod) { var type = AccessTools.TypeByName("AlphaBiomes.Command_SetStoneType"); buildingField = AccessTools.FieldRefAccess <Building>(type, "building"); // SyncWorker needed as the <ProcessInput> methods require syncing of the `building` field MP.RegisterSyncWorker <Command>(SyncSetStoneType, type, shouldConstruct: true); MpCompat.RegisterLambdaMethod(type, "ProcessInput", Enumerable.Range(0, 6).ToArray()); var rngFixMethods = new[] { "AlphaBiomes.CompGasProducer:CompTick", "AlphaBiomes.TarSprayer:SteamSprayerTick", "AlphaBiomes.GameCondition_AcidRain:DoCellSteadyEffects", }; PatchingUtilities.PatchSystemRand(AccessTools.Constructor(AccessTools.TypeByName("AlphaBiomes.CompGasProducer")), false); PatchingUtilities.PatchPushPopRand(rngFixMethods); }
public VanillaExpandedFramework(ModContentPack mod) { var type = AccessTools.TypeByName("ItemProcessor.Building_ItemProcessor"); // _1 and _5 are used to check if gizmo should be enabled, so we don't sync them MpCompat.RegisterSyncMethodsByIndex(type, "<GetGizmos>", 0, 2, 3, 4, 6, 7); type = AccessTools.TypeByName("ItemProcessor.Command_SetQualityList"); itemProcessorField = AccessTools.Field(type, "building"); MP.RegisterSyncWorker <Command>(SyncSetTargetQuality, type, shouldConstruct: true); MpCompat.RegisterSyncMethodsByIndex(type, "<ProcessInput>", Enumerable.Range(0, 8).ToArray()); // Keep an eye on this in the future, seems like something the devs could combine into a single class at some point foreach (var ingredientNumber in new[] { "First", "Second", "Third" }) { type = AccessTools.TypeByName($"ItemProcessor.Command_Set{ingredientNumber}ItemList"); MP.RegisterSyncWorker <Command>(SyncSetIngredientCommand, type, shouldConstruct: true); MP.RegisterSyncMethod(type, $"TryInsert{ingredientNumber}Thing"); MpCompat.RegisterSyncMethodsByIndex(type, "<ProcessInput>", 0); } // AddHediff desyncs with Arbiter, but seems fine without it PatchingUtilities.PatchPushPopRand("VanillaCookingExpanded.Thought_Hediff:MoodOffset"); }
public MiscTraining(ModContentPack mod) { PatchingUtilities.PatchPushPopRand("TrainingFacility.JobDriver_Archery:ShootArrow"); }
public VanillaPowerExpanded(ModContentPack mod) { Type type; // Gizmos // Debug fill/empty { type = AccessTools.TypeByName("GasNetwork.CompGasStorage"); // Both these methods are calling (basically) the same method, // but that method also has other callers that don't need syncing MpCompat.RegisterLambdaMethod(type, "CompGetGizmosExtra", 0, 1).SetDebugOnly(); } // Order to or cancel plugging the hole (method names shared by both types) { var types = new[] { "VanillaPowerExpanded.Building_ChemfuelPond", "VanillaPowerExpanded.Building_GasGeyser", }; foreach (var typeName in types) { type = AccessTools.TypeByName(typeName); MP.RegisterSyncMethod(type, "SetHoleForPlugging"); MP.RegisterSyncMethod(type, "CancelHoleForPlugging"); } } // Violence generator { type = AccessTools.TypeByName("VanillaPowerExpanded.CompSoulsPowerPlant"); MpCompat.RegisterLambdaMethod(type, "CompGetGizmosExtra", 1); // Toggle on/off } // RNG Fix { // Patch GasNetwork.MapComponent_WindDirection ctor PatchingUtilities.PatchSystemRand(AccessTools.Constructor(AccessTools.TypeByName("GasNetwork.MapComponent_WindDirection"), new Type[] { typeof(Map) }), false); var methods = new[] { "VanillaPowerExpanded.Building_SmallBattery:Tick", "VanillaPowerExpanded.Building_SmallBattery:PostApplyDamage", "VanillaPowerExpanded.WeatherEvent_CustomLightningStrike:FireEvent", "VanillaPowerExpanded.MapComponentExtender:doMapSpawns", "VanillaPowerExpanded.CompPlantHarmRadiusIfBroken:CompTick", // HarmRandomPlantInRadius is only called by CompPlantHarmRadiusIfBroken:CompTick, no need for patching // CompPowerPlantNuclear:AffectCell is only calling a seeded random "VanillaPowerExpanded.IntermittentGasSprayer:SteamSprayerTick", // IntermittentGasSprayer - NewBaseAirPuff is only called by ThrowAirPuffUp which is called by SteamSprayerTick, no need for patching // Building_GasGeyser:StartSpray is assigned to IntermittentGasSprayer:startSprayCallback, which is called from SteamSprayerTick "GasNetwork.GasNet:GasNetTick", "GasNetwork.MapComponent_WindDirection:MapGenerated", // PipeNetGrid pushes and pops all Rand calls, no need to patch // CompPowerAdvancedWater:RebuildCache is only calling a seeded random }; // These methods are loading resources in their .ctor, must be patched later var methodsForLater = new[] { "VanillaPowerExpanded.CompPowerAdvancedWater:PostSpawnSetup", "VanillaPowerExpanded.CompPowerAdvancedWind:PostSpawnSetup", }; PatchingUtilities.PatchPushPopRand(methods); LongEventHandler.ExecuteWhenFinished(() => PatchingUtilities.PatchPushPopRand(methodsForLater)); // Wind map comp windDirectionField = AccessTools.FieldRefAccess <float>(AccessTools.TypeByName("GasNetwork.MapComponent_WindDirection"), "windDirection"); MpCompat.harmony.Patch(AccessTools.Method("GasNetwork.MapComponent_WindDirection:MapComponentTick"), prefix: new HarmonyMethod(typeof(VanillaPowerExpanded), nameof(ReplaceWindMapComponentTick))); // GasNet utilities MpCompat.harmony.Patch(AccessTools.Method("GasNetwork.Utilities:HashOffsetTicks"), prefix: new HarmonyMethod(typeof(VanillaPowerExpanded), nameof(ReplaceHashOffsetTicks))); } }
public VanillaExpandedFramework(ModContentPack mod) { // ItemProcessor { var type = AccessTools.TypeByName("ItemProcessor.Building_ItemProcessor"); // _1, _5 and _7 are used to check if gizmo should be enabled, so we don't sync them MpCompat.RegisterLambdaMethod(type, "GetGizmos", 0, 2, 3, 4, 6, 8, 9, 10); type = AccessTools.TypeByName("ItemProcessor.Command_SetQualityList"); MP.RegisterSyncWorker <Command>(SyncCommandWithBuilding, type, shouldConstruct: true); MpCompat.RegisterLambdaMethod(type, "ProcessInput", Enumerable.Range(0, 8).ToArray()); type = AccessTools.TypeByName("ItemProcessor.Command_SetOutputList"); MP.RegisterSyncWorker <Command>(SyncCommandWithBuilding, type, shouldConstruct: true); MP.RegisterSyncMethod(type, "TryConfigureIngredientsByOutput"); // Keep an eye on this in the future, seems like something the devs could combine into a single class at some point foreach (var ingredientNumber in new[] { "First", "Second", "Third", "Fourth" }) { type = AccessTools.TypeByName($"ItemProcessor.Command_Set{ingredientNumber}ItemList"); MP.RegisterSyncWorker <Command>(SyncSetIngredientCommand, type, shouldConstruct: true); MP.RegisterSyncMethod(type, $"TryInsert{ingredientNumber}Thing"); MpCompat.RegisterLambdaMethod(type, "ProcessInput", 0); } } // Vanilla Cooking Expanded { // AddHediff desyncs with Arbiter, but seems fine without it PatchingUtilities.PatchPushPopRand("VanillaCookingExpanded.Thought_Hediff:MoodOffset"); } // VFE Core { MpCompat.RegisterLambdaMethod("VFECore.CompPawnDependsOn", "CompGetGizmosExtra", 0).SetDebugOnly(); learnedAbilitiesField = AccessTools.Field(AccessTools.TypeByName("VFECore.Abilities.CompAbilities"), "learnedAbilities"); MP.RegisterSyncWorker <ITargetingSource>(SyncVEFAbility, AccessTools.TypeByName("VFECore.Abilities.Ability")); } // Vanilla Furniture Expanded { MpCompat.RegisterLambdaMethod("VanillaFurnitureExpanded.CompConfigurableSpawner", "CompGetGizmosExtra", 0).SetDebugOnly(); var type = AccessTools.TypeByName("VanillaFurnitureExpanded.Command_SetItemsToSpawn"); MpCompat.RegisterLambdaDelegate(type, "ProcessInput", 1); MP.RegisterSyncWorker <Command>(SyncCommandWithBuilding, type, shouldConstruct: true); MpCompat.RegisterLambdaMethod("VanillaFurnitureExpanded.CompRockSpawner", "CompGetGizmosExtra", 0); type = AccessTools.TypeByName("VanillaFurnitureExpanded.Command_SetStoneType"); setStoneBuildingField = AccessTools.Field(type, "building"); MpCompat.RegisterLambdaMethod(type, "ProcessInput", 0); MP.RegisterSyncWorker <Command>(SyncSetStoneTypeCommand, type, shouldConstruct: true); MpCompat.RegisterLambdaDelegate(type, "ProcessInput", 1); type = AccessTools.TypeByName("VanillaFurnitureExpanded.CompRandomBuildingGraphic"); MpCompat.RegisterLambdaMethod(type, "CompGetGizmosExtra", 0); } // Vanilla Faction Mechanoids { var type = AccessTools.TypeByName("VFE.Mechanoids.CompMachineChargingStation"); MpCompat.RegisterLambdaDelegate(type, "CompGetGizmosExtra", 1, 6).SetContext(SyncContext.MapSelected); MpCompat.RegisterLambdaDelegate(type, "CompGetGizmosExtra", 4); } // AnimalBehaviours { // RNG PatchingUtilities.PatchSystemRand("AnimalBehaviours.DamageWorker_ExtraInfecter:ApplySpecialEffectsToPart", false); var rngFixConstructors = new[] { "AnimalBehaviours.CompAnimalProduct", "AnimalBehaviours.CompFilthProducer", "AnimalBehaviours.CompGasProducer", "AnimalBehaviours.CompInitialHediff", "AnimalBehaviours.DeathActionWorker_DropOnDeath", }; PatchingUtilities.PatchSystemRandCtor(rngFixConstructors, false); // Gizmos var type = AccessTools.TypeByName("AnimalBehaviours.CompDestroyThisItem"); MP.RegisterSyncMethod(type, "SetObjectForDestruction"); MP.RegisterSyncMethod(type, "CancelObjectForDestruction"); } // MVCF (Multi Verb Combat Framework) { var type = AccessTools.TypeByName("MVCF.WorldComponent_MVCF"); mvcfGetWorldCompMethod = AccessTools.Method(type, "GetComp"); mvcfAllManagersListField = AccessTools.Field(type, "allManagers"); mvcfManagersTableField = AccessTools.Field(type, "managers"); MP.RegisterSyncMethod(typeof(VanillaExpandedFramework), nameof(SyncedInitVerbManager)); MpCompat.harmony.Patch(AccessTools.Method(type, "GetManagerFor"), prefix: new HarmonyMethod(typeof(VanillaExpandedFramework), nameof(GetManagerForPrefix))); type = AccessTools.TypeByName("MVCF.VerbManager"); MP.RegisterSyncWorker <object>(SyncVerbManager, type, isImplicit: true); mvcfVerbManagerCtor = AccessTools.Constructor(type); mvcfInitializeManagerMethod = AccessTools.Method(type, "Initialize"); mvcfPawnGetter = AccessTools.PropertyGetter(type, "Pawn"); mvcfVerbsField = AccessTools.Field(type, "verbs"); var weakReferenceType = typeof(System.WeakReference <>).MakeGenericType(new[] { type }); weakReferenceCtor = AccessTools.FirstConstructor(weakReferenceType, ctor => ctor.GetParameters().Count() == 1); var conditionalWeakTableType = typeof(System.Runtime.CompilerServices.ConditionalWeakTable <,>).MakeGenericType(new[] { typeof(Pawn), type }); conditionalWeakTableAddMethod = AccessTools.Method(conditionalWeakTableType, "Add"); conditionalWeakTableTryGetValueMethod = AccessTools.Method(conditionalWeakTableType, "TryGetValue"); type = AccessTools.TypeByName("MVCF.ManagedVerb"); mvcfManagerVerbManagerField = AccessTools.Field(type, "man"); MP.RegisterSyncWorker <object>(SyncManagedVerb, type, isImplicit: true); // Seems like selecting the Thing that holds the verb inits some stuff, so we need to set the context MP.RegisterSyncMethod(type, "Toggle"); type = AccessTools.TypeByName("MVCF.Harmony.Gizmos"); MpCompat.RegisterLambdaDelegate(type, "GetGizmos_Postfix", 1); // Fire at will MpCompat.RegisterLambdaDelegate(type, "GetAttackGizmos_Postfix", 4); // Interrupt Attack MpCompat.RegisterLambdaDelegate(type, "Pawn_GetGizmos_Postfix", 0); // Also interrupt Attack } // Explosive Trails Effect { // RNG PatchingUtilities.PatchPushPopRand("ExplosiveTrailsEffect.SmokeThrowher:ThrowSmokeTrail"); } // KCSG (Custom Structure Generation) { // RNG var methods = new[] { "KCSG.SymbolResolver_AddFields:Resolve", "KCSG.SymbolResolver_Settlement:GenerateRooms", }; PatchingUtilities.PatchSystemRand(methods, false); } }
public GeneticRimCompat(ModContentPack mod) { Type type; // Several Gizmos { type = AccessTools.TypeByName("DraftingPatcher.Pawn_GetGizmos_Patch"); string[] methods = { "<AddGizmo>b__0", "<AddGizmo>b__1", "<AddGizmo>b__10", "<AddGizmo>b__11", "<AddGizmo>b__12", "<AddGizmo>b__13", "<AddGizmo>b__14", "<AddGizmo>b__15", "<AddGizmo>b__16", "<AddGizmo>b__17", "<AddGizmo>b__3", "<AddGizmo>b__5", "<AddGizmo>b__7", "<AddGizmo>b__8", "<AddGizmo>b__9", }; foreach (string method in methods) { MP.RegisterSyncDelegate(type, "<>c__DisplayClass0_0", method); } } // ArchotechShip startup { MP.RegisterSyncMethod(AccessTools.Method("NewMachinery.ArchotechUtility:StartupHibernatingParts")); MP.RegisterSyncMethod(AccessTools.Method("NewMachinery.ArchotechCountdown:InitiateCountdown")); } { type = AccessTools.TypeByName("NewMachinery.ArchotechCountdown"); string[] methods = { "InitiateCountdown", "CancelCountdown", "CountdownEnded" }; foreach (string method in methods) { MP.RegisterSyncMethod(AccessTools.Method(type, method)); } } // Genepod { type = AccessTools.TypeByName("NewMachinery.Building_NewGenePod"); MP.RegisterSyncMethod(type, "<GetGizmos>b__20_0"); MP.RegisterSyncMethod(type, "<GetGizmos>b__20_1"); } // Commands { MP.RegisterSyncMethod(AccessTools.Method("NewMachinery.Command_SetGene2List:ProcessInput")); MP.RegisterSyncMethod(AccessTools.Method("NewMachinery.Command_SetGeneList:ProcessInput")); } // RNG patching { string[] constructorsToPatch = { "NewHatcher.CompHatcherRandomizer", "NewHatcher.CompIncubator", "NewHatcher.CompRecombinator", "NewHatcher.CompRecombinatorSerum", }; PatchingUtilities.PatchSystemRandCtor(constructorsToPatch, false); string[] methodsWithRand = { "NewHatcher.CompHatcherRandomizer:Hatch", "NewHatcher.CompIncubator:Hatch", "NewHatcher.CompRecombinator:Hatch", "NewHatcher.CompRecombinator:RecombinateAgain", "NewHatcher.CompRecombinatorSerum:Hatch", }; PatchingUtilities.PatchPushPopRand(methodsWithRand); } }
public GeneticRimCompat(ModContentPack mod) { Type type; // Several Gizmos { type = AccessTools.TypeByName("GeneticRim.GeneticRim_Pawn_GetGizmos_Patch"); string[] methods = { "<AddGizmo>b__0", "<AddGizmo>b__1", "<AddGizmo>b__10", "<AddGizmo>b__11", "<AddGizmo>b__12", "<AddGizmo>b__13", "<AddGizmo>b__14", "<AddGizmo>b__15", "<AddGizmo>b__16", "<AddGizmo>b__17", "<AddGizmo>b__3", "<AddGizmo>b__5", "<AddGizmo>b__7", "<AddGizmo>b__8", "<AddGizmo>b__9", }; foreach (string method in methods) { MP.RegisterSyncDelegate(type, "<>c__DisplayClass0_0", method); } } // ArchotechShip startup { MP.RegisterSyncMethod(AccessTools.Method("GeneticRim.ArchotechUtility:StartupHibernatingParts")); MP.RegisterSyncMethod(AccessTools.Method("GeneticRim.ArchotechCountdown:InitiateCountdown")); } { type = AccessTools.TypeByName("GeneticRim.ArchotechCountdown"); string[] methods = { "InitiateCountdown", "CancelCountdown", "CountdownEnded" }; foreach (string method in methods) { MP.RegisterSyncMethod(AccessTools.Method(type, method)); } } // RNG patching { string[] constructorsToPatch = { "GeneticRim.CompHatcherRandomizer", "GeneticRim.CompIncubator", "GeneticRim.CompRecombinator", "GeneticRim.CompRecombinatorSerum", "GeneticRim.DeathActionWorker_Eggxplosion", "GeneticRim.CompExploder", }; PatchingUtilities.PatchSystemRandCtor(constructorsToPatch, false); string[] methodsWithRand = { "GeneticRim.CompHatcherRandomizer:Hatch", "GeneticRim.CompIncubator:Hatch", "GeneticRim.CompRecombinator:Hatch", "GeneticRim.CompRecombinator:RecombinateAgain", "GeneticRim.CompRecombinatorSerum:Hatch", "GeneticRim.DeathActionWorker_Eggxplosion:PawnDied", "GeneticRim.CompExploder:wickInitializer", }; PatchingUtilities.PatchPushPopRand(methodsWithRand); } }
public VanillaExpandedFramework(ModContentPack mod) { // ItemProcessor { var type = AccessTools.TypeByName("ItemProcessor.Building_ItemProcessor"); // _1, _5 and _7 are used to check if gizmo should be enabled, so we don't sync them MpCompat.RegisterSyncMethodsByIndex(type, "<GetGizmos>", 0, 2, 3, 4, 6, 8, 9, 10); type = AccessTools.TypeByName("ItemProcessor.Command_SetQualityList"); MP.RegisterSyncWorker <Command>(SyncCommandWithBuilding, type, shouldConstruct: true); MpCompat.RegisterSyncMethodsByIndex(type, "<ProcessInput>", Enumerable.Range(0, 8).ToArray()); type = AccessTools.TypeByName("ItemProcessor.Command_SetOutputList"); MP.RegisterSyncWorker <Command>(SyncCommandWithBuilding, type, shouldConstruct: true); MP.RegisterSyncMethod(type, "TryConfigureIngredientsByOutput"); // Keep an eye on this in the future, seems like something the devs could combine into a single class at some point foreach (var ingredientNumber in new[] { "First", "Second", "Third", "Fourth" }) { type = AccessTools.TypeByName($"ItemProcessor.Command_Set{ingredientNumber}ItemList"); MP.RegisterSyncWorker <Command>(SyncSetIngredientCommand, type, shouldConstruct: true); MP.RegisterSyncMethod(type, $"TryInsert{ingredientNumber}Thing"); MpCompat.RegisterSyncMethodsByIndex(type, "<ProcessInput>", 0); } } // Vanilla Cooking Expanded { // AddHediff desyncs with Arbiter, but seems fine without it PatchingUtilities.PatchPushPopRand("VanillaCookingExpanded.Thought_Hediff:MoodOffset"); } // VFE Core { var type = AccessTools.TypeByName("VFECore.CompPawnDependsOn"); MpCompat.RegisterSyncMethodByIndex(type, "<CompGetGizmosExtra>", 0).SetDebugOnly(); } // Vanilla Furniture Expanded { var type = AccessTools.TypeByName("VanillaFurnitureExpanded.CompConfigurableSpawner"); MpCompat.RegisterSyncMethodByIndex(type, "<CompGetGizmosExtra>", 0).SetDebugOnly(); type = AccessTools.TypeByName("VanillaFurnitureExpanded.Command_SetItemsToSpawn"); MP.RegisterSyncDelegate(type, "<>c__DisplayClass2_0", "<ProcessInput>b__1"); type = AccessTools.TypeByName("VanillaFurnitureExpanded.CompRockSpawner"); MpCompat.RegisterSyncMethodByIndex(type, "<CompGetGizmosExtra>", 0); type = AccessTools.TypeByName("VanillaFurnitureExpanded.Command_SetStoneType"); setStoneBuildingField = AccessTools.Field(type, "building"); MpCompat.RegisterSyncMethodByIndex(type, "<ProcessInput>", 0); MP.RegisterSyncWorker <Command>(SyncSetStoneTypeCommand, type, shouldConstruct: true); MP.RegisterSyncDelegate(type, "<>c__DisplayClass2_0", "<ProcessInput>b__1"); } // Vanilla Faction Mechanoids { var type = AccessTools.TypeByName("VFE.Mechanoids.CompMachineChargingStation"); MP.RegisterSyncDelegate(type, "<>c", "<CompGetGizmosExtra>b__21_1", Array.Empty <string>()).SetContext(SyncContext.MapSelected); MP.RegisterSyncDelegate(type, "<>c", "<CompGetGizmosExtra>b__21_6", Array.Empty <string>()).SetContext(SyncContext.MapSelected); MP.RegisterSyncDelegate(type, "<>c__DisplayClass21_0", "<CompGetGizmosExtra>b__4"); } // AnimalBehaviours { // RNG PatchingUtilities.PatchSystemRand("AnimalBehaviours.DamageWorker_ExtraInfecter:ApplySpecialEffectsToPart", false); PatchingUtilities.PatchSystemRandCtor(new[] { "AnimalBehaviours.CompAnimalProduct", "AnimalBehaviours.CompGasProducer" }, false); // Gizmos // Might not work, as I could not find a mod that uses this to test this var type = AccessTools.TypeByName("AnimalBehaviours.CompDestroyThisItem"); MP.RegisterSyncMethod(type, "SetObjectForDestruction"); MP.RegisterSyncMethod(type, "CancelObjectForDestruction"); } // MVCF (Multi Verb Combat Framework) { var type = AccessTools.TypeByName("MVCF.WorldComponent_MVCF"); mvcfGetWorldCompMethod = AccessTools.Method(type, "GetComp"); mvcfAllManagersListField = AccessTools.Field(type, "allManagers"); mvcfManagersTableField = AccessTools.Field(type, "managers"); MP.RegisterSyncMethod(typeof(VanillaExpandedFramework), nameof(SyncedInitVerbManager)); MpCompat.harmony.Patch(AccessTools.Method(type, "GetManagerFor"), prefix: new HarmonyMethod(typeof(VanillaExpandedFramework), nameof(GetManagerForPrefix))); type = AccessTools.TypeByName("MVCF.VerbManager"); MP.RegisterSyncWorker <object>(SyncVerbManager, type, isImplicit: true); mvcfVerbManagerCtor = AccessTools.Constructor(type); mvcfInitializeManagerMethod = AccessTools.Method(type, "Initialize"); mvcfPawnGetter = AccessTools.PropertyGetter(type, "Pawn"); mvcfVerbsField = AccessTools.Field(type, "verbs"); var weakReferenceType = typeof(System.WeakReference <>).MakeGenericType(new[] { type }); weakReferenceCtor = AccessTools.FirstConstructor(weakReferenceType, ctor => ctor.GetParameters().Count() == 1); var conditionalWeakTableType = typeof(System.Runtime.CompilerServices.ConditionalWeakTable <,>).MakeGenericType(new[] { typeof(Pawn), type }); conditionalWeakTableAddMethod = AccessTools.Method(conditionalWeakTableType, "Add"); conditionalWeakTableTryGetValueMethod = AccessTools.Method(conditionalWeakTableType, "TryGetValue"); type = AccessTools.TypeByName("MVCF.ManagedVerb"); mvcfManagerVerbManagerField = AccessTools.Field(type, "man"); MP.RegisterSyncWorker <object>(SyncManagedVerb, type, isImplicit: true); // Seems like selecting the Thing that holds the verb inits some stuff, so we need to set the context MP.RegisterSyncMethod(type, "Toggle"); type = AccessTools.TypeByName("MVCF.Harmony.Gizmos"); MP.RegisterSyncDelegate(type, "<>c__DisplayClass5_0", "<GetGizmos_Postfix>b__1"); // Fire at will MP.RegisterSyncDelegate(type, "<>c__DisplayClass6_0", "<GetAttackGizmos_Postfix>b__4"); // Interrupt Attack MP.RegisterSyncDelegate(type, "<>c__DisplayClass7_0", "<Pawn_GetGizmos_Postfix>b__0"); // Also interrupt Attack } }
public VanillaPowerExpanded(ModContentPack mod) { Type type; /// Gizmos // Debug fill/empty { type = AccessTools.TypeByName("GasNetwork.CompGasStorage"); // Both these methods are calling (basically) the same method, // but that method also has other callers that don't need syncing MpCompat.RegisterSyncMethodsByIndex(type, "<CompGetGizmosExtra>", 0, 1); type = AccessTools.TypeByName("VanillaPowerExpanded.CompPipeTank"); // This method is only called by 2 gizmos and nothing else (as far as I can tell) MP.RegisterSyncMethod(type, "SetStoredEnergyPct"); } // Order to or cancel plugging the hole (method names shared by both types) { var types = new[] { "VanillaPowerExpanded.Building_ChemfuelPond", "VanillaPowerExpanded.Building_GasGeyser", }; foreach (var typeName in types) { type = AccessTools.TypeByName(typeName); MP.RegisterSyncMethod(type, "SetHoleForPlugging"); MP.RegisterSyncMethod(type, "CancelHoleForPlugging"); } } // RNG Fix { var methods = new[] { "VanillaPowerExpanded.Building_SmallBattery:Tick", "VanillaPowerExpanded.Building_SmallBattery:PostApplyDamage", "VanillaPowerExpanded.WeatherEvent_CustomLightningStrike:FireEvent", "VanillaPowerExpanded.MapComponentExtender:doMapSpawns", "VanillaPowerExpanded.CompPlantHarmRadiusIfBroken:CompTick", // HarmRandomPlantInRadius is only called by CompPlantHarmRadiusIfBroken:CompTick, no need for patching "VanillaPowerExpanded.CompPowerPlantNuclear:AffectCell", "VanillaPowerExpanded.Building_GasGeyser:StartSpray", "VanillaPowerExpanded.GasExplosionUtility:TryStartFireNear", "VanillaPowerExpanded.IncidentWorker_GasExplosion:TryExecuteWorker", "VanillaPowerExpanded.IntermittentGasSprayer:SteamSprayerTick", "VanillaPowerExpanded.IntermittentGasSprayer:ThrowAirPuffUp", // NewBaseAirPuff is only called by IntermittentGasSprayer:ThrowAirPuffUp, no need for patching "VanillaPowerExpanded.GasPipeNet:PowerNetTick", "GasNetwork.GasNet:GasNetTick", // PipeNetGrid pushes and pops all Rand calls, no need to patch // CompPowerAdvancedWater:RebuildCache is only calling a seeded random }; // These methods are loading resources in their .ctor, must be patched later var methodsForLater = new[] { //"VanillaPowerExpanded.Building_Tank:Tick", //"VanillaPowerExpanded.Building_Tank:PostApplyDamage", "VanillaPowerExpanded.CompPowerAdvancedWater:PostSpawnSetup", "VanillaPowerExpanded.CompPowerAdvancedWind:PostSpawnSetup", }; PatchingUtilities.PatchPushPopRand(methods); LongEventHandler.ExecuteWhenFinished(() => PatchingUtilities.PatchPushPopRand(methodsForLater)); } }