/// <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 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 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); } }
/// <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 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> /// 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 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 } })); }
/// <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 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> /// 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 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>)))); }
internal static TranspiledMethod Transpiler(TranspiledMethod instructions, MethodBase original) { var rtb = typeof(TagBits).MakeByRefType(); return(PPatchTools.ReplaceMethodCallSafe(instructions, typeof(TagBits). GetMethodSafe(nameof(TagBits.Or), false, rtb), typeof(TagBitOps). GetMethodSafe(nameof(TagBitOps.Or), true, rtb, rtb))); }
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)))); }
/// <summary> /// Transpiles LoadAnims to start up anim loading in the background. /// </summary> internal static TranspiledMethod Transpiler(TranspiledMethod instructions) { return(PPatchTools.ReplaceMethodCallSafe(instructions, new Dictionary <MethodInfo, MethodInfo>() { { typeof(KAnimGroupFile).GetMethodSafe(nameof(KAnimGroupFile.LoadAll), true), typeof(AsyncLoadPatches).GetMethodSafe(nameof(LoadAnims), true) }, { typeof(KAnimBatchManager).GetMethodSafe(nameof(KAnimBatchManager. CompleteInit), false), PPatchTools.RemoveCall } })); }
/// <summary> /// Transpiles Insert to take out a lock before adding. /// </summary> internal static TranspiledMethod Transpiler(TranspiledMethod instructions) { return(PPatchTools.ReplaceMethodCallSafe(instructions, new Dictionary <MethodInfo, MethodInfo>() { { typeof(SceneEntryHash).GetMethodSafe(nameof(SceneEntryHash.Add), false, typeof(ScenePartitionerEntry)), typeof(ScenePartitioner_Insert_Patch).GetMethodSafe(nameof(AddLocked), true, typeof(SceneEntryHash), typeof(ScenePartitionerEntry)) }, { typeof(List <DirtyNode>).GetMethodSafe(nameof(List <DirtyNode> .Add), false, typeof(DirtyNode)), typeof(ScenePartitioner_Insert_Patch).GetMethodSafe(nameof(AddLocked), true, typeof(List <DirtyNode>), typeof(DirtyNode)) } })); }
/// <summary> /// Applied to Steam to avoid dialog spam on startup if many mods are updated or /// installed. /// </summary> private static TranspiledMethod TranspileUpdateMods(TranspiledMethod method) { return(PPatchTools.ReplaceMethodCallSafe(method, new Dictionary <MethodInfo, MethodInfo>() { { typeof(Manager).GetMethodSafe(nameof(Manager.Report), false, typeof(GameObject)), typeof(QueuedReportManager).GetMethodSafe(nameof(QueuedReportManager. QueueDelayedReport), true, typeof(Manager), typeof(GameObject)) }, { typeof(Manager).GetMethodSafe(nameof(Manager.Sanitize), false, typeof(GameObject)), typeof(QueuedReportManager).GetMethodSafe(nameof(QueuedReportManager. QueueDelayedSanitize), true, typeof(Manager), typeof(GameObject)) } })); }
internal static TranspiledMethod Transpiler(TranspiledMethod method) { return(PPatchTools.ReplaceMethodCallSafe(method, new Dictionary <MethodInfo, MethodInfo>() { { typeof(Sim).GetMethodSafe(nameof(Sim.SIM_Initialize), true, PPatchTools.AnyArguments), PPatchTools.RemoveCall }, { typeof(SimMessages).GetMethodSafe(nameof(SimMessages. CreateSimElementsTable), true, PPatchTools.AnyArguments), PPatchTools.RemoveCall }, { typeof(SimMessages).GetMethodSafe(nameof(SimMessages.CreateDiseaseTable), true, PPatchTools.AnyArguments), PPatchTools.RemoveCall } })); }
/// <summary> /// Transpiles RenderMesh to insert a call to a pipe filter right after the context /// calculates what pipes are visible to render. /// </summary> internal static TranspiledMethod Transpiler(TranspiledMethod instructions) { TranspiledMethod result; // Lower priority optimization: use CameraController.Instance.VisibleArea to // save some math var oldArea = typeof(GridVisibleArea).GetMethodSafe(nameof(GridVisibleArea. GetVisibleArea), true); var newArea = typeof(ConduitFlowVisualizer_RenderMesh_Patch).GetMethodSafe( nameof(GetVisibleArea), true); if (oldArea != null && newArea != null) { result = PPatchTools.ReplaceMethodCallSafe(instructions, oldArea, newArea); #if DEBUG PUtil.LogDebug("Patched ConduitFlowVisualizer.RenderMesh"); #endif } else { result = instructions; } return(result); }
/// <summary> /// Transpiles the target methods to remove a bunch of method calls. /// </summary> internal static TranspiledMethod Transpiler(TranspiledMethod instructions) { return(PPatchTools.ReplaceMethodCallSafe(instructions, new Dictionary <MethodInfo, MethodInfo>() { { typeof(KMod.Manager).GetMethodSafe(nameof(KMod.Manager.Load), false, typeof(KMod.Content)), PPatchTools.RemoveCall }, { typeof(ProcGen.SettingsCache).GetMethodSafe(nameof(ProcGen. SettingsCache.Clear), true), PPatchTools.RemoveCall }, { typeof(ProcGenGame.WorldGen).GetMethodSafe(nameof(ProcGenGame.WorldGen. LoadSettings), true), PPatchTools.RemoveCall }, { typeof(KMod.Manager).GetMethodSafe(nameof(KMod.Manager.Report), false, typeof(GameObject)), PPatchTools.RemoveCall } })); }
/// <summary> /// Transpiles End to replace the DrawMesh call with a call to update the mesh /// attributes. /// </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 replacement = typeof(ConduitFlowMeshPatches).GetMethodSafe( nameof(PostUpdate), true, typeof(Mesh), typeof(Vector3), typeof(Quaternion), typeof(Material), typeof(int)); var newMethod = instructions; if (drawMesh != null) { newMethod = PPatchTools.ReplaceMethodCallSafe(instructions, drawMesh, replacement); } else { PUtil.LogWarning("Unable to patch ConduitFlowMesh.End"); } foreach (var instr in newMethod) { yield return(instr); } }
/// <summary> /// Transpiles OnPrefabInit to remove slow method calls. /// </summary> internal static TranspiledMethod Transpiler(TranspiledMethod instructions) { return(PPatchTools.ReplaceMethodCallSafe(instructions, typeof(CodexCache). GetMethodSafe(nameof(CodexCache.CodexCacheInit), true), typeof(AsyncLoadPatches).GetMethodSafe(nameof(AsyncLoadCodex), true))); }
/// <summary> /// Transpiles AddToSim to make it never spawn the sound. /// </summary> internal static TranspiledMethod Transpiler(TranspiledMethod instructions) { return(PPatchTools.ReplaceMethodCallSafe(instructions, MAYBE_AUDIBLE, NEVER_AUDIBLE)); }