private static void RoomsExpandedCompat() { var db = Db.Get(); var RoomsExpanded = PPatchTools.GetTypeSafe("RoomsExpanded.RoomTypes_AllModded", "RoomsExpandedMerged"); if (RoomsExpanded != null) { PUtil.LogDebug("RoomsExpanded found. Attempt to add compatibility."); try { AquariumRoom = (RoomType)RoomsExpanded.GetPropertySafe <RoomType>("Aquarium", true)?.GetValue(null, null); if (AquariumRoom != null) { var upgrade_paths = db.RoomTypes.CreaturePen.upgrade_paths.AddToArray(AquariumRoom); Traverse.Create(db.RoomTypes.CreaturePen).Property(nameof(RoomType.upgrade_paths)).SetValue(upgrade_paths); Traverse.Create(AquariumRoom).Property(nameof(RoomType.priority)).SetValue(db.RoomTypes.CreaturePen.priority); RoomsExpandedFound = true; } } catch (System.Exception e) { PUtil.LogExcWarn(e); } } if (RoomsExpandedFound) { harmony.PatchTranspile(typeof(RanchStation.Instance), nameof(RanchStation.Instance.FindRanchable), new HarmonyMethod(typeof(RanchStation_Instance_FindRanchable), nameof(RanchStation_Instance_FindRanchable.TranspilerCompat))); } }
private static IEnumerable <CodeInstruction> Transpiler(IEnumerable <CodeInstruction> instructions, MethodBase method) { var PlayAnim = typeof(GameStateMachine <BaggedStates, BaggedStates.Instance, IStateMachineTarget, BaggedStates.Def> .State).GetMethodSafe("PlayAnim", false, typeof(string), typeof(KAnim.PlayMode)); var Stub = typeof(BaggedStates_InitializeStates).GetMethodSafe(nameof(PlayAnimStub), true, PPatchTools.AnyArguments); return(PPatchTools.ReplaceMethodCall(instructions, PlayAnim, Stub)); }
internal PRemoteLightWrapper(object other) { if (other == null) { throw new ArgumentNullException(nameof(other)); } if (!PPatchTools.TryGetPropertyValue(other, nameof(ILightShape.KleiLightShape), out LightShape ls)) { throw new ArgumentException("Light shape is missing KleiLightShape"); } KleiLightShape = ls; if (!PPatchTools.TryGetPropertyValue(other, nameof(ILightShape.Identifier), out string id) || id == null) { throw new ArgumentException("Light shape is missing KleiLightShape"); } Identifier = id; if (!PPatchTools.TryGetPropertyValue(other, nameof(ILightShape.RayMode), out LightShape rm)) { rm = (LightShape)(-1); } RayMode = rm; var otherType = other.GetType(); fillLight = otherType.CreateDelegate <FillLightDelegate>(nameof(PLightShape. DoFillLight), other, typeof(GameObject), typeof(int), typeof(int), typeof(BrightnessDict)); if (fillLight == null) { throw new ArgumentException("Light shape is missing FillLight"); } }
/// <summary> /// Adds buttons to a mod entry to move the mod around. /// </summary> /// <param name="displayedMod">The mod entry to modify.</param> /// <param name="instance">The Mods screen that is the parent of these entries.</param> internal static void ConfigureRowInstance(object displayedMod, ModsScreen instance) { if (displayedMod == null) { throw new ArgumentNullException(nameof(displayedMod)); } var type = displayedMod.GetType(); if (!PPatchTools.TryGetFieldValue(displayedMod, "mod_index", out int index)) { throw new ArgumentException("Unable to get mod index"); } if (!PPatchTools.TryGetFieldValue(displayedMod, "rect_transform", out Transform transform)) { throw new ArgumentException("Unable to get rect transform"); } var refs = transform.gameObject.GetComponentSafe <HierarchyReferences>(); KButton button; // "More mod actions" if (refs != null && (button = refs.GetReference <KButton>(REF_MORE)) != null) { var onAction = new ModActionDelegates(button, index, instance.gameObject); button.onClick += onAction.TogglePopup; button.gameObject.AddOrGet <ToolTip>().OnToolTip = onAction.GetDescription; } }
/// <summary> /// Transpiles TriggerVisualNotification to remove calls to the bouncy coroutine. /// </summary> internal static TranspiledMethod Transpiler(TranspiledMethod instructions) { return(PPatchTools.ReplaceMethodCallSafe(instructions, typeof(DiagnosticRow). GetMethodSafe(nameof(DiagnosticRow.VisualNotificationRoutine), false), typeof(DiagnosticRow_TriggerVisualNotification_Patch).GetMethodSafe(nameof( NoMoveRoutine), true, typeof(DiagnosticRow)))); }
internal static void AfterDbInit() { // Assets are now loaded, so create pip icon var pip = Assets.GetAnim("squirrel_kanim"); Sprite sprite = null; if (pip != null) { sprite = Def.GetUISpriteFromMultiObjectAnim(pip); } if (sprite == null) { // Pip anim is somehow missing? sprite = Assets.GetSprite("overlay_farming"); } Assets.Sprites.Add(PipPlantOverlayStrings.OVERLAY_ICON, sprite); // SPPR fixes the symmetry rule bool ruleFix = PPatchTools.GetTypeSafe("MightyVincent.Patches", "SimplerPipPlantRule") != null; if (ruleFix) { PUtil.LogDebug("Detected Simpler Pip Plant Overlay, adjusting radius"); } PipPlantOverlayTests.SymmetricalRadius = ruleFix; }
/// <summary> /// Transpiles PrioritizableRenderer to first update the mesh renderer status, then /// disable the actual Graphics.DrawMesh call. /// </summary> internal static TranspiledMethod Transpiler(TranspiledMethod instructions) { var target = typeof(PrioritizableMeshRenderer).GetMethodSafe(nameof( PrioritizableMeshRenderer.SetInstanceVisibility), true); var drawMesh = typeof(Graphics).GetMethodSafe(nameof(Graphics.DrawMesh), true, typeof(Mesh), typeof(Vector3), typeof(Quaternion), typeof(Material), typeof(int), typeof(Camera), typeof(int), typeof(MaterialPropertyBlock), typeof(bool), typeof(bool)); var recalculateBounds = typeof(Mesh).GetMethodSafe(nameof(Mesh.RecalculateBounds), false); yield return(new CodeInstruction(OpCodes.Call, target)); var newMethod = instructions; // Assigning triangles automatically recalculates bounds! if (drawMesh != null && recalculateBounds != null) { newMethod = PPatchTools.ReplaceMethodCallSafe(instructions, new Dictionary <MethodInfo, MethodInfo> { { drawMesh, PPatchTools.RemoveCall }, { recalculateBounds, PPatchTools.RemoveCall } }); } else { PUtil.LogWarning("Unable to patch PrioritizableRenderer.RenderEveryTick"); } foreach (var instr in newMethod) { yield return(instr); } }
/// <summary> /// Transpiles LateUpdate to disable all of the relevant Graphics.DrawMesh calls. /// Leaves the worldPlane ones for now. /// </summary> internal static TranspiledMethod Transpiler(TranspiledMethod instructions) { var drawMesh = typeof(Graphics).GetMethodSafe(nameof(Graphics.DrawMesh), true, typeof(Mesh), typeof(Vector3), typeof(Quaternion), typeof(Material), typeof(int)); var target = typeof(Material).GetMethodSafe(nameof(Material.SetTexture), false, typeof(string), typeof(Texture)); var replacement = typeof(TerrainBG_LateUpdate_Patch).GetMethodSafe(nameof( SetTexture), true, typeof(Material), typeof(string), typeof(Texture)); var newMethod = instructions; if (drawMesh != null && target != null && replacement != null) { newMethod = PPatchTools.ReplaceMethodCallSafe(instructions, new Dictionary <MethodInfo, MethodInfo>() { { drawMesh, PPatchTools.RemoveCall }, { target, replacement } }); } else { PUtil.LogWarning("Unable to patch TerrainBG.LateUpdate"); } foreach (var instr in newMethod) { yield return(instr); } }
private static IEnumerable <CodeInstruction> Transpiler(IEnumerable <CodeInstruction> instructions, MethodBase method, ILGenerator IL) { string methodName = method.DeclaringType.FullName + "." + method.Name; var SetGasProvider = typeof(OxygenBreather).GetMethodSafe(nameof(OxygenBreather.SetGasProvider), false, PPatchTools.AnyArguments); var Stub = typeof(ClusterTelescope_ClusterTelescopeWorkable_OnWorkableEvent_Oxygen).GetMethodSafe(nameof(StubSetGasProvider), true, PPatchTools.AnyArguments); bool result = false; if (SetGasProvider != null && Stub != null) { instructions = PPatchTools.ReplaceMethodCall(instructions, SetGasProvider, Stub); result = true; } if (!result) { PUtil.LogWarning($"Could not apply Transpiler to the '{methodName}'"); } #if DEBUG else { PUtil.LogDebug($"'{methodName}' Transpiler injected"); } #endif return(instructions); }
/// <summary> /// Transpiles AsyncPathProbe to use our job manager instead. /// </summary> internal static TranspiledMethod Transpiler(TranspiledMethod instructions) { var workItemType = typeof(IWorkItemCollection); var cpuCharge = typeof(PathProbeJobManager).GetMethodSafe(nameof( PathProbeJobManager.SetCPUBudget), true, typeof(ICPULoad)); return(PPatchTools.ReplaceMethodCallSafe(instructions, new Dictionary <MethodInfo, MethodInfo> { { typeof(GlobalJobManager).GetMethodSafe(nameof(GlobalJobManager.Run), true, workItemType), typeof(PathProbeJobManager).GetMethodSafe(nameof(PathProbeJobManager. RunAsync), true, workItemType) }, { typeof(CPUBudget).GetMethodSafe(nameof(CPUBudget.Start), true, typeof(ICPULoad)), cpuCharge }, { typeof(CPUBudget).GetMethodSafe(nameof(CPUBudget.End), true, typeof(ICPULoad)), cpuCharge } })); }
internal static TranspiledMethod TranspileRefresh(TranspiledMethod instructions) { return(PPatchTools.ReplaceMethodCallSafe(instructions, typeof(RoomProber). GetMethodSafe(nameof(RoomProber.SolidChangedEvent), false, typeof(int), typeof(bool)), typeof(DecorProviderRefreshFix).GetMethodSafe(nameof( SolidNotChangedEvent), true, typeof(RoomProber), typeof(int), typeof(bool)))); }
/// <summary> /// Initializes the list of discovered resources, accounting for both DLC and Vanilla. /// </summary> private void InitDiscovered() { Type baseType; object instance; // TODO Vanilla/DLC code if ((baseType = PPatchTools.GetTypeSafe("DiscoveredResources")) == null) { // Vanilla baseType = PPatchTools.GetTypeSafe(nameof(WorldInventory)); instance = baseType?.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(null, null); } else { // DLC instance = baseType.GetFieldSafe("Instance", true)?.GetValue(null); } #if DEBUG PUtil.LogDebug("Using inventory type: " + (baseType?.Name ?? "None")); #endif if (instance != null) { discovered = baseType.CreateDelegate <ResourceCheckDelegate>( "TryGetDiscoveredResourcesFromTag", instance, typeof(Tag), typeof( HashSet <Tag>).MakeByRefType()); } else { PUtil.LogWarning("Unable to find discovered resource list, no resources will be available to sweep"); } }
internal BetterInfoCardsCompat() { RegisterMethodFunc addConv = null; exportMethod = null; try { addConv = PPatchTools.GetTypeSafe(BIC_NAMESPACE + "ConverterManager", BIC_ASSEMBLY)?.Detour <RegisterMethodFunc>("AddConverterReflect"); var patchType = PPatchTools.GetTypeSafe(BIC_NAMESPACE + "CollectHoverInfo", BIC_ASSEMBLY)?.GetNestedType("GetSelectInfo_Patch", BindingFlags.Static | BindingFlags.Instance | PPatchTools.BASE_FLAGS); if (patchType != null) { exportMethod = patchType.Detour <ExportMethodFunc>("Export"); } } catch (AmbiguousMatchException e) { PUtil.LogWarning("Exception when loading Better Info Cards compatibility:"); PUtil.LogExcWarn(e); } catch (DetourException e) { PUtil.LogWarning("Exception when loading Better Info Cards compatibility:"); PUtil.LogExcWarn(e); } if (addConv != null && exportMethod != null) { try { Register(addConv, EXPORT_THERMAL_MASS, ObjectToFloat, SumThermalMass); Register(addConv, EXPORT_HEAT_ENERGY, ObjectToFloat, SumHeatEnergy); PUtil.LogDebug("Registered Better Info Cards status data handlers"); } catch (Exception e) { PUtil.LogWarning("Exception when registering Better Info Cards compatibility:"); PUtil.LogExcWarn(e.GetBaseException()); } } }
/// <summary> /// Transpiles OnMouseMove to call through a filter method. /// </summary> internal static TranspiledMethod Transpiler(TranspiledMethod instructions) { return(PPatchTools.ReplaceMethodCallSafe(instructions, typeof(BuildTool). GetMethodSafe(nameof(BuildTool.UpdateVis), false, typeof(Vector3)), typeof( BuildToolPatches).GetMethodSafe(nameof(BuildToolPatches.ShouldUpdateVis), true, typeof(BuildTool), typeof(Vector3)))); }
/// <summary> /// Transpiles the constructor to enqueue the item onto the reachability queue instead /// of checking immediately (where, on load, the result would be invalid). /// </summary> internal static TranspiledMethod Transpiler(TranspiledMethod instructions) { return(PPatchTools.ReplaceMethodCallSafe(instructions, typeof(RMI).GetMethodSafe( nameof(RMI.UpdateReachability), false), typeof(ReachabilityMonitor_Instance_Constructor_Patch).GetMethodSafe(nameof( UpdateReachability), true, typeof(RMI)))); }
/// <summary> /// Transpiles SlicedSim1000ms to wrap accumulator calls with our own. /// </summary> internal static IEnumerable <CodeInstruction> Transpiler( IEnumerable <CodeInstruction> method) { return(PPatchTools.ReplaceMethodCall(method, typeof(Accumulators). GetMethodSafe(nameof(Accumulators.GetAverageRate), false, typeof( IntHandle)), typeof(ResourcesInMotionPatches).GetMethodSafe(nameof( GracefulAccumulate), true, PPatchTools.AnyArguments))); }
/// <summary> /// Transpiles Place to properly place special buildings. /// </summary> internal static IEnumerable <CodeInstruction> Transpiler( IEnumerable <CodeInstruction> method) { return(PPatchTools.ReplaceMethodCall(method, typeof(BuildingDef).GetMethodSafe( nameof(BuildingDef.Build), false, PPatchTools.AnyArguments), typeof(SandboxToolsPatches).GetMethodSafe(nameof(BuildFixedMaterials), true, PPatchTools.AnyArguments))); }
/// <summary> /// Transpiles Widthdraw (Clay please spelling) to take out a lock before removing. /// </summary> internal static TranspiledMethod Transpiler(TranspiledMethod instructions) { return(PPatchTools.ReplaceMethodCallSafe(instructions, typeof(SceneEntryHash). GetMethodSafe(nameof(SceneEntryHash.Remove), false, typeof( ScenePartitionerEntry)), typeof(ScenePartitioner_Widthdraw_Patch). GetMethodSafe(nameof(RemoveLocked), true, typeof(SceneEntryHash), typeof( ScenePartitionerEntry)))); }
/// <summary> /// Transpiles GatherEntries to take out a lock before subtracting. /// </summary> internal static TranspiledMethod Transpiler(TranspiledMethod instructions) { return(PPatchTools.ReplaceMethodCallSafe(instructions, typeof(SceneEntryHash). GetMethodSafe(nameof(SceneEntryHash.ExceptWith), false, typeof( IEnumerable <ScenePartitionerEntry>)), typeof( ScenePartitioner_GatherEntries_Patch).GetMethodSafe(nameof(ExceptWithLocked), true, typeof(SceneEntryHash), typeof(IEnumerable <ScenePartitionerEntry>)))); }
/// <summary> /// Transpiles SetActiveResearch to rip out a Sort call in the middle. /// </summary> internal static IEnumerable <CodeInstruction> Transpiler( IEnumerable <CodeInstruction> method) { return(PPatchTools.ReplaceMethodCall(method, typeof(List <TechInstance>). GetMethodSafe("Sort", false, new Type[] { typeof(Comparison <TechInstance>) }))); }
/// <summary> /// Transpiles the methods to remove the GameScheduler calls that create the tutorial /// messages. /// </summary> internal static TranspiledMethod Transpiler(TranspiledMethod instructions) { return(PPatchTools.ReplaceMethodCallSafe(instructions, typeof(GameScheduler). GetMethodSafe(nameof(GameScheduler.Schedule), false, typeof(string), typeof( float), typeof(Action <object>), typeof(object), typeof(SchedulerGroup)), typeof(DisableTutorialSchedulerPatch).GetMethodSafe(nameof(DoNotSchedule), true, PPatchTools.AnyArguments))); }
/// <summary> /// Applied before DoStateTransition runs. /// </summary> internal static IEnumerable <CodeInstruction> Transpiler( IEnumerable <CodeInstruction> method) { return(PPatchTools.ReplaceMethodCall(method, typeof(Util).GetMethodSafe( nameof(Util.KDestroyGameObject), true, typeof(GameObject)), typeof(MoreAchievementsPatches).GetMethodSafe(nameof(CheckAndDestroy), true, typeof(GameObject)))); }
/// <summary> /// Transpiles Update to replace calls to a specific AddTargetIfVisible version with /// a version that is not only a bit faster, but also sets the conduit visible when it /// matches the criteria. /// /// This works around a Harmony bug where the wrong generic methods were being patched. /// </summary> internal static TranspiledMethod Transpiler(TranspiledMethod instructions) { return(PPatchTools.ReplaceMethodCallSafe(instructions, typeof(OverlayModes.Mode). GetMethod(nameof(OverlayModes.Mode.AddTargetIfVisible), PPatchTools. BASE_FLAGS | BindingFlags.Instance)?.MakeGenericMethod(typeof(SaveLoadRoot)), typeof(OverlayModes_Modes_Patch).GetMethodSafe(nameof(AddTargetIfVisible), true, PPatchTools.AnyArguments))); }
/// <summary> /// Transpiles UpdateOverloadTime to fix round off issues. /// </summary> internal static IEnumerable <CodeInstruction> Transpiler( IEnumerable <CodeInstruction> method) { return(PPatchTools.ReplaceMethodCall(method, typeof(Wire).GetMethodSafe( nameof(Wire.GetMaxWattageAsFloat), true, typeof(Wire.WattageRating)), typeof(StockBugsPatches).GetMethodSafe(nameof(GetRoundedMaxWattage), true, typeof(Wire.WattageRating)))); }
/// <summary> /// Transpiles RefreshCreatureCount to check the right tile for creatures. /// </summary> internal static IEnumerable <CodeInstruction> Transpiler( IEnumerable <CodeInstruction> method) { return(PPatchTools.ReplaceMethodCall(method, typeof(Grid).GetMethodSafe( nameof(Grid.PosToCell), true, typeof(KMonoBehaviour)), typeof(StockBugsPatches).GetMethodSafe(nameof(PosToCorrectedCell), true, typeof(KMonoBehaviour)))); }
public static IEnumerable <CodeInstruction> Transpiler(IEnumerable <CodeInstruction> method) { return(PPatchTools.ReplaceMethodCall(method, typeof(MinionStartingStats).GetMethodSafe("Apply", false, typeof(GameObject)), typeof(NewBaseScreen_SpawnMinions_Transpiler).GetMethodSafe("DoXpGive", true, typeof(MinionStartingStats), typeof(GameObject)) )); }
internal static TranspiledMethod Transpiler(TranspiledMethod instructions, MethodBase original) { var rtb = typeof(TagBits).MakeByRefType(); return(PPatchTools.ReplaceMethodCall(instructions, typeof(TagBits). GetMethodSafe(nameof(TagBits.Or), false, rtb), typeof(TagBitOps). GetMethodSafe(nameof(TagBitOps.Or), true, rtb, rtb))); }
internal static IEnumerable <CodeInstruction> Transpiler(IEnumerable <CodeInstruction> method) { return(PPatchTools.ReplaceMethodCall(method, new Dictionary <MethodInfo, MethodInfo>() { { typeof(Sim).GetMethodSafe(nameof(Sim.SIM_Initialize), true, PPatchTools.AnyArguments), null }, { typeof(SimMessages).GetMethodSafe(nameof(SimMessages.CreateSimElementsTable), true, PPatchTools.AnyArguments), null }, { typeof(SimMessages).GetMethodSafe(nameof(SimMessages.CreateDiseaseTable), true, PPatchTools.AnyArguments), null } })); }
/// <summary> /// Transpiles DoWorldDamage to destroy tiles more intelligently. /// </summary> internal static IEnumerable <CodeInstruction> Transpiler( IEnumerable <CodeInstruction> method) { // There are 2 overloads, so types must be specified return(PPatchTools.ReplaceMethodCall(method, typeof(WorldDamage).GetMethodSafe( nameof(WorldDamage.ApplyDamage), false, typeof(int), typeof(float), typeof(int), typeof(int), typeof(string), typeof(string)), typeof(StockBugsPatches).GetMethodSafe(nameof(ApplyRocketDamage), true, PPatchTools.AnyArguments))); }
private static IEnumerable <CodeInstruction> LightBuffer_LateUpdate_Transpile( IEnumerable <CodeInstruction> body) { var target = typeof(Light2D).GetPropertySafe <LightShape>(nameof(Light2D.shape), false)?.GetGetMethod(true); return((target == null) ? body : PPatchTools.ReplaceMethodCallSafe(body, target, typeof(PLightManager).GetMethodSafe(nameof(PLightManager.LightShapeToRayShape), true, typeof(Light2D)))); }