Decompiled source of TwoRadarMaps v1.6.0
TwoRadarMaps.dll
Decompiled a month ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using EnhancedRadarBooster; using GameNetcodeStuff; using HarmonyLib; using ImmersiveCompany.Patches; using Microsoft.CodeAnalysis; using OpenBodyCams; using OpenBodyCams.API; using TMPro; using TwoRadarMaps.Compatibility; using TwoRadarMaps.Patches; using TwoRadarMaps.Utilities.IL; using Unity.Netcode; using UnityEngine; using UnityEngine.Rendering; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("OpenBodyCams")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("OpenBodyCams")] [assembly: AssemblyCopyright("Copyright © 2025")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("58be1122-f068-4465-95ee-b1f09dcd559f")] [assembly: AssemblyFileVersion("3.0.5")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("3.0.5.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class IsUnmanagedAttribute : Attribute { } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace TwoRadarMaps { [BepInPlugin("Zaggy1024.TwoRadarMaps", "TwoRadarMaps", "1.6.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { private const string MOD_NAME = "TwoRadarMaps"; private const string MOD_UNIQUE_NAME = "Zaggy1024.TwoRadarMaps"; private const string MOD_VERSION = "1.6.0"; internal static readonly Harmony Harmony = new Harmony("Zaggy1024.TwoRadarMaps"); public static ConfigEntry<FilterMode> TextureFiltering; public static ConfigEntry<int> BodyCamHorizontalResolution; public static ConfigEntry<bool> EnableZoom; public static ConfigEntry<string> ZoomLevels; public static ConfigEntry<int> DefaultZoomLevel; public static ConfigEntry<bool> EnableTeleportCommand; public static ConfigEntry<bool> EnableTeleportCommandShorthand; private const string OLD_DEFAULT_ZOOM_LEVELS = "19.7, 29.55, 39.4"; private const string DEFAULT_ZOOM_LEVELS = "30, 45, 60"; internal static Terminal Terminal; internal static ShipTeleporter Teleporter; public static ManualCameraRenderer TerminalMapRenderer; public static TextMeshProUGUI TerminalMapScreenPlayerName; public static Canvas TerminalMapScreenUICanvas; public static float[] TerminalMapZoomLevelOptions; public static int TerminalMapZoomLevel; public static ConfigEntry<string> LastConfigVersion; public static Plugin Instance { get; private set; } public ManualLogSource Logger => ((BaseUnityPlugin)this).Logger; public void Awake() { Instance = this; TextureFiltering = ((BaseUnityPlugin)this).Config.Bind<FilterMode>("Rendering", "TextureFiltering", (FilterMode)0, "The filtering mode to apply to the map (and the body cam if present).\n\nPoint will result in sharp edges on pixels.\nBilinear and Trilinear will result in smooth transitions between pixels."); TextureFiltering.SettingChanged += delegate { //IL_0014: Unknown result type (might be due to invalid IL or missing references) ((Texture)TerminalMapRenderer.cam.targetTexture).filterMode = TextureFiltering.Value; OpenBodyCamsCompatibility.UpdateBodyCamTexture(); }; BodyCamHorizontalResolution = ((BaseUnityPlugin)this).Config.Bind<int>("Compatibility", "BodyCamHorizontalResolution", 170, "The horizontal resolution to use for the picture-in-picture body cam when it is enabled in OpenBodyCams 2.1.0+.\n\nThe vertical resolution will be calculated based on a 4:3 aspect ratio."); EnableZoom = ((BaseUnityPlugin)this).Config.Bind<bool>("Zoom", "Enabled", false, "Enable 'zoom in' and 'zoom out' commands in the terminal to zoom in and out of the terminal radar map."); EnableZoom.SettingChanged += delegate { TerminalCommands.Initialize(); }; ZoomLevels = ((BaseUnityPlugin)this).Config.Bind<string>("Zoom", "Sizes", "30, 45, 60", "The orthographic sizes to use for each zoom level.\nA list of comma-separated numbers.\nLower values indicate a smaller field of view.\n100% zoom is 30."); ZoomLevels.SettingChanged += delegate { UpdateZoomFactors(); }; DefaultZoomLevel = ((BaseUnityPlugin)this).Config.Bind<int>("Zoom", "DefaultLevel", 0, "The zoom factor to select by default. The first zoom level is 0."); EnableTeleportCommand = ((BaseUnityPlugin)this).Config.Bind<bool>("TeleportCommand", "Enabled", false, "Enable an 'activate teleport' command in the terminal. A player can be specified to teleport them instead of the target of the terminal's map."); EnableTeleportCommand.SettingChanged += delegate { TerminalCommands.Initialize(); }; EnableTeleportCommandShorthand = ((BaseUnityPlugin)this).Config.Bind<bool>("TeleportCommand", "ShorthandEnabled", true, "Enable a 'tp' shorthand for the 'activate teleport' command. Will only function if the longhand command is enabled."); EnableTeleportCommandShorthand.SettingChanged += delegate { TerminalCommands.Initialize(); }; LastConfigVersion = ((BaseUnityPlugin)this).Config.Bind<string>("Debug", "LastConfigVersion", "", "The last version of the mod that loaded/saved this config file. Used for setting migration."); MigrateConfigOptions(); Harmony.PatchAll(typeof(PatchTerminal)); Harmony.PatchAll(typeof(PatchVanillaBugs)); Harmony.PatchAll(typeof(PatchManualCameraRenderer)); Harmony.PatchAll(typeof(PatchShipTeleporter)); RenderPipelineManager.beginCameraRendering += BeforeCameraRendering; OpenBodyCamsCompatibility.Initialize(); EnhancedRadarBoosterCompatibility.Initialize(Harmony); } private void MigrateConfigOptions() { if (!Version.TryParse(LastConfigVersion.Value, out Version result)) { result = new Version(1, 5, 0); } Logger.LogInfo((object)$"Last config version is {result}."); if (result < new Version(1, 6, 0) && ZoomLevels.Value == "19.7, 29.55, 39.4") { Logger.LogInfo((object)$"{((ConfigEntryBase)ZoomLevels).Definition} is being migrated to factors that correspond to the new map size in v70."); ZoomLevels.Value = "30, 45, 60"; } LastConfigVersion.Value = "1.6.0"; } public static void BeforeCameraRendering(ScriptableRenderContext context, Camera camera) { ManualCameraRenderer val = StartOfRound.Instance?.mapScreen; if ((Object)(object)val == (Object)null) { return; } ManualCameraRenderer val2 = null; ((Renderer)val.lineFromRadarTargetToExit).forceRenderingOff = true; if ((Object)(object)camera == (Object)(object)val.cam) { val2 = val; } if ((Object)(object)TerminalMapRenderer != (Object)null) { ((Renderer)TerminalMapRenderer.lineFromRadarTargetToExit).forceRenderingOff = true; if ((Object)(object)camera == (Object)(object)TerminalMapRenderer.cam) { val2 = TerminalMapRenderer; } } if (!((Object)(object)val2 == (Object)null)) { ((Renderer)val2.lineFromRadarTargetToExit).forceRenderingOff = false; SetContourMapVisibility(val2); } } private static void SetContourMapVisibility(ManualCameraRenderer map) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) GameObject contourMap = map.contourMap; if (!((Object)(object)contourMap == (Object)null)) { if ((Object)(object)map.targetedPlayer == (Object)null && ((Component)map.headMountedCamTarget).transform.position.y >= -80f) { map.contourMap.SetActive(false); return; } if ((Object)(object)map.targetedPlayer != (Object)null && map.targetedPlayer.isInsideFactory) { map.contourMap.SetActive(false); return; } map.contourMap.SetActive(true); map.contourMap.transform.position = new Vector3(contourMap.transform.position.x, ((Component)map.headMountedCamTarget).transform.position.y - 1.5f, contourMap.transform.position.z); } } private static bool TargetIsValid(Transform targetTransform) { if ((Object)(object)targetTransform == (Object)null) { return false; } PlayerControllerB val = default(PlayerControllerB); if (!((Component)((Component)targetTransform).transform).TryGetComponent<PlayerControllerB>(ref val)) { return true; } if (!val.isPlayerControlled && !val.isPlayerDead) { return (Object)(object)val.redirectToEnemy != (Object)null; } return true; } internal static void SetTargetIndex(ManualCameraRenderer mapRenderer, int targetIndex) { if (targetIndex >= 0 && targetIndex < mapRenderer.radarTargets.Count) { mapRenderer.targetTransformIndex = targetIndex; mapRenderer.targetedPlayer = ((Component)mapRenderer.radarTargets[targetIndex].transform).GetComponent<PlayerControllerB>(); } } internal static int GetNextValidTarget(List<TransformAndName> targets, int initialIndex) { int count = targets.Count; for (int i = 0; i < count; i++) { int num = (initialIndex + i) % count; if (TargetIsValid(targets[num]?.transform)) { return num; } } return -1; } internal static void StartTargetTransition(ManualCameraRenderer mapRenderer, int targetIndex) { if (mapRenderer.updateMapCameraCoroutine != null) { ((MonoBehaviour)mapRenderer).StopCoroutine(mapRenderer.updateMapCameraCoroutine); } mapRenderer.updateMapCameraCoroutine = ((MonoBehaviour)mapRenderer).StartCoroutine(mapRenderer.updateMapTarget(targetIndex, true)); } internal static void EnsureMapRendererHasValidTarget(ManualCameraRenderer mapRenderer) { int nextValidTarget = GetNextValidTarget(mapRenderer.radarTargets, mapRenderer.targetTransformIndex); if (nextValidTarget != -1) { StartTargetTransition(mapRenderer, nextValidTarget); } } public static void EnsureAllMapRenderersHaveValidTargets() { if (((NetworkBehaviour)StartOfRound.Instance.mapScreen).IsOwner) { EnsureMapRendererHasValidTarget(StartOfRound.Instance.mapScreen); } EnsureMapRendererHasValidTarget(TerminalMapRenderer); } public static void UpdateZoomFactors(string factors) { try { TerminalMapZoomLevelOptions = (from s in factors.Split(new char[2] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries) select float.Parse(s.Trim(), CultureInfo.InvariantCulture)).ToArray(); } catch (Exception arg) { Instance.Logger.LogError((object)$"Failed to parse terminal map radar zoom levels: {arg}"); UpdateZoomFactors("30, 45, 60"); } SetZoomLevel(DefaultZoomLevel.Value); } public static void UpdateZoomFactors() { UpdateZoomFactors(ZoomLevels.Value); } public static float GetZoomOrthographicSize() { return TerminalMapZoomLevelOptions[TerminalMapZoomLevel]; } public static void SetZoomLevel(int level) { if (!((Object)(object)TerminalMapRenderer == (Object)null)) { TerminalMapRenderer.mapCameraAnimator.SetTrigger("Transition"); TerminalMapZoomLevel = Math.Max(0, Math.Min(level, TerminalMapZoomLevelOptions.Length - 1)); TerminalMapRenderer.cam.orthographicSize = GetZoomOrthographicSize(); } } public static void CycleTerminalMapZoom() { SetZoomLevel((TerminalMapZoomLevel + 1) % TerminalMapZoomLevelOptions.Length); } public static void ZoomTerminalMapIn() { SetZoomLevel(TerminalMapZoomLevel - 1); } public static void ZoomTerminalMapOut() { SetZoomLevel(TerminalMapZoomLevel + 1); } public static void TeleportTarget(int targetIndex) { ManualCameraRenderer mapScreen = StartOfRound.Instance.mapScreen; if (mapScreen.targetTransformIndex >= mapScreen.radarTargets.Count) { Instance.Logger.LogError((object)$"Attempted to teleport target #{targetIndex} which is out of bounds of the {mapScreen.radarTargets.Count} targets available."); } else if ((Object)(object)Teleporter == (Object)null) { Instance.Logger.LogError((object)$"Attempted to teleport target #{targetIndex} ({mapScreen.radarTargets[targetIndex].name}) with no teleporter."); } else if (!(Teleporter.cooldownTime > 0f)) { int targetTransformIndex = mapScreen.targetTransformIndex; SetTargetIndex(mapScreen, targetIndex); Teleporter.PressTeleportButtonOnLocalClient(); SetTargetIndex(mapScreen, targetTransformIndex); } } } public static class TerminalCommands { public static TerminalNode CycleZoomNode = null; public static TerminalNode ZoomInNode = null; public static TerminalNode ZoomOutNode = null; public static TerminalNode ResetZoomNode = null; public static TerminalNode TeleportNode = null; private static readonly List<TerminalKeyword> newTerminalKeywords = new List<TerminalKeyword>(); private static readonly List<TerminalKeyword> modifiedTerminalKeywords = new List<TerminalKeyword>(); private static readonly List<(TerminalNode, string)> appendedDescriptions = new List<(TerminalNode, string)>(); public static void Initialize() { //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Expected O, but got Unknown //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Expected O, but got Unknown //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_01ad: Unknown result type (might be due to invalid IL or missing references) //IL_01b4: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Expected O, but got Unknown //IL_0238: Unknown result type (might be due to invalid IL or missing references) //IL_023d: Unknown result type (might be due to invalid IL or missing references) //IL_0244: Unknown result type (might be due to invalid IL or missing references) //IL_0250: Expected O, but got Unknown if ((Object)(object)Plugin.Terminal == (Object)null) { return; } RemoveAddedKeywords(); Plugin.UpdateZoomFactors(); CycleZoomNode = null; ZoomInNode = null; ZoomOutNode = null; ResetZoomNode = null; if (Plugin.EnableZoom.Value) { CycleZoomNode = ScriptableObject.CreateInstance<TerminalNode>(); ((Object)CycleZoomNode).name = "CycleZoomNode"; CycleZoomNode.displayText = ""; CycleZoomNode.clearPreviousText = true; ZoomInNode = ScriptableObject.CreateInstance<TerminalNode>(); ((Object)ZoomInNode).name = "ZoomIn"; ZoomInNode.displayText = ""; ZoomInNode.clearPreviousText = true; ZoomOutNode = ScriptableObject.CreateInstance<TerminalNode>(); ((Object)ZoomOutNode).name = "ZoomOut"; ZoomOutNode.displayText = ""; ZoomOutNode.clearPreviousText = true; ResetZoomNode = ScriptableObject.CreateInstance<TerminalNode>(); ((Object)ResetZoomNode).name = "ResetZoom"; ResetZoomNode.displayText = ""; ResetZoomNode.clearPreviousText = true; TerminalKeyword noun = FindOrCreateKeyword("In", "in", verb: false); TerminalKeyword noun2 = FindOrCreateKeyword("Out", "out", verb: false); FindOrCreateKeyword("Zoom", "zoom", verb: true, (CompatibleNoun[])(object)new CompatibleNoun[2] { new CompatibleNoun { noun = noun, result = ZoomInNode }, new CompatibleNoun { noun = noun2, result = ZoomOutNode } }).specialKeywordResult = CycleZoomNode; TerminalKeyword noun3 = FindOrCreateKeyword("Zoom", "zoom", verb: false); FindOrCreateKeyword("Reset", "reset", verb: true, (CompatibleNoun[])(object)new CompatibleNoun[1] { new CompatibleNoun { noun = noun3, result = ResetZoomNode } }); AddCommandDescription("other", "ZOOM", "Cycle through zoom levels on the map. Specify direction with 'IN' and 'OUT'.\nThe 'RESET ZOOM' command will set the zoom back to the default level."); } TeleportNode = null; if (Plugin.EnableTeleportCommand.Value) { TeleportNode = ScriptableObject.CreateInstance<TerminalNode>(); ((Object)TeleportNode).name = "TeleportNode"; TeleportNode.clearPreviousText = true; TerminalKeyword noun4 = FindOrCreateKeyword("Teleporter", "teleporter", verb: false); FindOrCreateKeyword("Activate", "activate", verb: true, (CompatibleNoun[])(object)new CompatibleNoun[1] { new CompatibleNoun { noun = noun4, result = TeleportNode } }); string text = ""; if (Plugin.EnableTeleportCommandShorthand.Value) { FindOrCreateKeyword("TeleportShorthand", "tp", verb: true).specialKeywordResult = TeleportNode; text = "/TP"; } AddCommandDescription("other", "ACTIVATE TELEPORTER" + text, "Activate the teleporter to beam the player monitored on the map into the ship."); } AddNewlyCreatedCommands(); } public static bool ProcessNode(TerminalNode node) { if ((Object)(object)node == (Object)(object)CycleZoomNode) { Plugin.CycleTerminalMapZoom(); return false; } if ((Object)(object)node == (Object)(object)ZoomInNode) { Plugin.ZoomTerminalMapIn(); return false; } if ((Object)(object)node == (Object)(object)ZoomOutNode) { Plugin.ZoomTerminalMapOut(); return false; } if ((Object)(object)node == (Object)(object)ResetZoomNode) { Plugin.SetZoomLevel(Plugin.DefaultZoomLevel.Value); return false; } if ((Object)(object)node == (Object)(object)TeleportNode) { if ((Object)(object)Plugin.Teleporter == (Object)null) { TeleportNode.displayText = "Teleporter is not installed.\n\n"; return true; } if (Plugin.Teleporter.cooldownTime > 0f) { TeleportNode.displayText = $"Teleporter is on cooldown for {(int)(Plugin.Teleporter.cooldownTime + 1f)} more seconds."; return true; } TeleportNode.displayText = "Teleporting " + StartOfRound.Instance.mapScreen.radarTargets[Plugin.TerminalMapRenderer.targetTransformIndex]?.name + "...\n\n"; Plugin.TeleportTarget(Plugin.TerminalMapRenderer.targetTransformIndex); return false; } return true; } private static TerminalKeyword FindKeyword(string word, bool verb) { return ((IEnumerable<TerminalKeyword>)Plugin.Terminal.terminalNodes.allKeywords).FirstOrDefault((Func<TerminalKeyword, bool>)((TerminalKeyword keyword) => keyword.word == word && keyword.isVerb == verb)); } private static CompatibleNoun FindCompatibleNoun(this TerminalKeyword keyword, string noun) { return ((IEnumerable<CompatibleNoun>)keyword.compatibleNouns).FirstOrDefault((Func<CompatibleNoun, bool>)((CompatibleNoun compatible) => compatible.noun.word == noun)); } private static TerminalKeyword FindOrCreateKeyword(string name, string word, bool verb, CompatibleNoun[] compatibleNouns = null) { Plugin.Instance.Logger.LogInfo((object)("Creating terminal " + (verb ? "verb" : "noun") + " '" + word + "' (" + name + ").")); TerminalKeyword val = FindKeyword(word, verb); if ((Object)(object)val == (Object)null) { val = ScriptableObject.CreateInstance<TerminalKeyword>(); ((Object)val).name = name; val.isVerb = verb; val.word = word; val.compatibleNouns = compatibleNouns; newTerminalKeywords.Add(val); Plugin.Instance.Logger.LogInfo((object)" Keyword was not found, created a new one."); } else { TerminalKeyword obj = val; CompatibleNoun[] array = val.compatibleNouns ?? Array.Empty<CompatibleNoun>(); CompatibleNoun[] array2 = compatibleNouns ?? Array.Empty<CompatibleNoun>(); int num = 0; CompatibleNoun[] array3 = (CompatibleNoun[])(object)new CompatibleNoun[array.Length + array2.Length]; ReadOnlySpan<CompatibleNoun> readOnlySpan = new ReadOnlySpan<CompatibleNoun>(array); readOnlySpan.CopyTo(new Span<CompatibleNoun>(array3).Slice(num, readOnlySpan.Length)); num += readOnlySpan.Length; ReadOnlySpan<CompatibleNoun> readOnlySpan2 = new ReadOnlySpan<CompatibleNoun>(array2); readOnlySpan2.CopyTo(new Span<CompatibleNoun>(array3).Slice(num, readOnlySpan2.Length)); num += readOnlySpan2.Length; obj.compatibleNouns = array3; Plugin.Instance.Logger.LogInfo((object)" Keyword existed, appended nouns."); } modifiedTerminalKeywords.Add(val); return val; } private static void AddNewlyCreatedCommands() { TerminalNodesList terminalNodes; TerminalKeyword[] allKeywords = (terminalNodes = Plugin.Terminal.terminalNodes).allKeywords; List<TerminalKeyword> list = newTerminalKeywords; int num = 0; TerminalKeyword[] array = (TerminalKeyword[])(object)new TerminalKeyword[allKeywords.Length + list.Count]; ReadOnlySpan<TerminalKeyword> readOnlySpan = new ReadOnlySpan<TerminalKeyword>(allKeywords); readOnlySpan.CopyTo(new Span<TerminalKeyword>(array).Slice(num, readOnlySpan.Length)); num += readOnlySpan.Length; foreach (TerminalKeyword item in list) { array[num] = item; num++; } terminalNodes.allKeywords = array; } private static void AddCommandDescription(string category, string word, string description) { TerminalNode specialKeywordResult = FindKeyword(category, verb: false).specialKeywordResult; string text = new StringBuilder(word.Length + description.Length + 5).Append(">").Append(word).Append("\n") .Append(description) .Append("\n\n") .ToString(); appendedDescriptions.Add((specialKeywordResult, text)); if (specialKeywordResult.displayText.EndsWith("\n\n\n")) { specialKeywordResult.displayText = specialKeywordResult.displayText.Insert(specialKeywordResult.displayText.Length - 1, text); } else { specialKeywordResult.displayText += text; } } private static void RemoveAddedKeywords() { foreach (TerminalKeyword modifiedTerminalKeyword in modifiedTerminalKeywords) { if (modifiedTerminalKeyword.compatibleNouns != null) { modifiedTerminalKeyword.compatibleNouns = modifiedTerminalKeyword.compatibleNouns.Where((CompatibleNoun compatible) => !newTerminalKeywords.Contains(compatible.noun)).ToArray(); } } modifiedTerminalKeywords.Clear(); foreach (TerminalKeyword newTerminalKeyword in newTerminalKeywords) { Object.Destroy((Object)(object)newTerminalKeyword); } TerminalNodesList terminalNodes = Plugin.Terminal.terminalNodes; terminalNodes.allKeywords = terminalNodes.allKeywords.Where((TerminalKeyword keyword) => !newTerminalKeywords.Contains(keyword)).ToArray(); newTerminalKeywords.Clear(); foreach (var appendedDescription in appendedDescriptions) { TerminalNode item = appendedDescription.Item1; string item2 = appendedDescription.Item2; int num = item.displayText.IndexOf(item2); if (num == -1) { Plugin.Instance.Logger.LogError((object)("Could not find command description text in " + ((Object)item).name + " to remove it:")); Plugin.Instance.Logger.LogError((object)item2); } else { item.displayText = item.displayText.Remove(num, item2.Length); } } appendedDescriptions.Clear(); } } } namespace TwoRadarMaps.Utilities.IL { internal class ILInjector { [CompilerGenerated] private sealed class <GetRelativeInstructions>d__31 : IEnumerable<CodeInstruction>, IEnumerable, IEnumerator<CodeInstruction>, IEnumerator, IDisposable { private int <>1__state; private CodeInstruction <>2__current; private int <>l__initialThreadId; public ILInjector <>4__this; private int offset; public int <>3__offset; private int size; public int <>3__size; private int <i>5__2; CodeInstruction IEnumerator<CodeInstruction>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <GetRelativeInstructions>d__31(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { int num = <>1__state; ILInjector iLInjector = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; <i>5__2 = 0; break; case 1: <>1__state = -1; <i>5__2++; break; } if (<i>5__2 < size) { <>2__current = iLInjector.instructions[iLInjector.index + offset + <i>5__2]; <>1__state = 1; return true; } return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator<CodeInstruction> IEnumerable<CodeInstruction>.GetEnumerator() { <GetRelativeInstructions>d__31 <GetRelativeInstructions>d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; <GetRelativeInstructions>d__ = this; } else { <GetRelativeInstructions>d__ = new <GetRelativeInstructions>d__31(0) { <>4__this = <>4__this }; } <GetRelativeInstructions>d__.offset = <>3__offset; <GetRelativeInstructions>d__.size = <>3__size; return <GetRelativeInstructions>d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<CodeInstruction>)this).GetEnumerator(); } } private const string INVALID = "Injector is invalid"; private List<CodeInstruction> instructions = instructions.ToList(); private ILGenerator generator; private int index; private int matchEnd; public bool IsValid { get { if (instructions != null) { return IsIndexValid(index); } return false; } } public CodeInstruction Instruction { get { if (!IsIndexInRange(index)) { return null; } return instructions[index]; } set { if (!IsIndexInRange(index)) { throw new InvalidOperationException($"Current index {index} is out of range of instruction count {instructions.Count}"); } instructions[index] = value; } } public CodeInstruction LastMatchedInstruction { get { int num = matchEnd - 1; if (!IsIndexInRange(num)) { return null; } return instructions[num]; } set { int num = matchEnd - 1; if (!IsIndexInRange(num)) { throw new InvalidOperationException($"Last matched index {index} is out of range of instruction count {instructions.Count}"); } instructions[num] = value; } } public ICollection<CodeInstruction> Instructions => instructions.AsReadOnly(); public ILInjector(IEnumerable<CodeInstruction> instructions, ILGenerator generator = null) { this.generator = generator; matchEnd = -1; base..ctor(); } public ILInjector GoToStart() { matchEnd = index; index = 0; return this; } public ILInjector GoToEnd() { matchEnd = index; index = instructions.Count; return this; } public ILInjector Forward(int offset) { if (!IsValid) { return this; } matchEnd = index; index = Math.Clamp(index + offset, -1, instructions.Count); return this; } public ILInjector Back(int offset) { return Forward(-offset); } private void MarkInvalid() { index = -1; matchEnd = -1; } private void Search(bool forward, ILMatcher[] predicates) { if (!IsValid) { return; } int num = 1; if (!forward) { num = -1; index--; } while (forward ? (index < instructions.Count) : (index >= 0)) { if (forward && index + predicates.Length > instructions.Count) { index = instructions.Count; break; } int i; for (i = 0; i < predicates.Length && predicates[i].Matches(instructions[index + i]); i++) { } if (i == predicates.Length) { matchEnd = index + i; return; } index += num; } MarkInvalid(); } public ILInjector Find(params ILMatcher[] predicates) { Search(forward: true, predicates); return this; } public ILInjector ReverseFind(params ILMatcher[] predicates) { Search(forward: false, predicates); return this; } public ILInjector GoToPush(int popIndex) { if (!IsValid) { return this; } matchEnd = index; index--; int num = 0; while (index >= 0) { CodeInstruction instruction = instructions[index]; num += instruction.PushCount(); num -= instruction.PopCount(); if (num > popIndex) { return this; } index--; } return this; } public ILInjector SkipBranch() { if (Instruction == null) { return this; } if (!(Instruction.operand is Label label)) { throw new InvalidOperationException($"Current instruction is not a branch: {Instruction}"); } return FindLabel(label); } public ILInjector FindLabel(Label label) { if (label == default(Label)) { return this; } matchEnd = index; for (index = 0; index < instructions.Count; index++) { if (instructions[index].labels.Contains(label)) { return this; } } MarkInvalid(); return this; } public ILInjector GoToMatchEnd() { index = matchEnd; return this; } public ILInjector GoToLastMatchedInstruction() { if (!IsIndexValid(matchEnd)) { return this; } index = matchEnd - 1; return this; } private bool IsIndexValid(int index) { return index != -1; } private bool IsIndexInRange(int index) { if (index >= 0) { return index < instructions.Count; } return false; } public CodeInstruction GetRelativeInstruction(int offset) { if (!IsValid) { throw new InvalidOperationException("Injector is invalid"); } int num = index + offset; if (!IsIndexInRange(num)) { throw new IndexOutOfRangeException($"Offset {offset} would read out of bounds at index {num}"); } return instructions[num]; } public ILInjector SetRelativeInstruction(int offset, CodeInstruction instruction) { if (!IsValid) { throw new InvalidOperationException("Injector is invalid"); } int num = index + offset; if (!IsIndexInRange(num)) { throw new IndexOutOfRangeException($"Offset {offset} would write out of bounds at index {num}"); } instructions[num] = instruction; return this; } [IteratorStateMachine(typeof(<GetRelativeInstructions>d__31))] public IEnumerable<CodeInstruction> GetRelativeInstructions(int offset, int size) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <GetRelativeInstructions>d__31(-2) { <>4__this = this, <>3__offset = offset, <>3__size = size }; } public IEnumerable<CodeInstruction> GetRelativeInstructions(int size) { return GetRelativeInstructions(0, size); } private void GetLastMatchRangeAbsolute(out int start, out int end) { start = index; end = matchEnd; if (start > end) { int num = end; int num2 = start; start = num; end = num2; } } private void GetLastMatchRange(out int start, out int size) { GetLastMatchRangeAbsolute(out start, out var end); if (start < 0 || start >= instructions.Count) { throw new InvalidOperationException($"Last match range starts at invalid index {start}"); } if (end < 0 || end > instructions.Count) { throw new InvalidOperationException($"Last match range ends at invalid index {end}"); } size = end - start; } public List<CodeInstruction> GetLastMatch() { GetLastMatchRange(out var start, out var size); return instructions.GetRange(start, size); } public ILInjector DefineLabel(out Label label) { if (generator == null) { throw new InvalidOperationException("No ILGenerator was provided"); } label = generator.DefineLabel(); return this; } public ILInjector AddLabel(out Label label) { DefineLabel(out label); return AddLabel(label); } public ILInjector AddLabel(Label label) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown Instruction = new CodeInstruction(Instruction); Instruction.labels.Add(label); return this; } public ILInjector InsertInPlace(params CodeInstruction[] instructions) { if (!IsValid) { throw new InvalidOperationException("Injector is invalid"); } this.instructions.InsertRange(index, instructions); if (matchEnd >= index) { matchEnd += instructions.Length; } return this; } public ILInjector Insert(params CodeInstruction[] instructions) { InsertInPlace(instructions); index += instructions.Length; return this; } public ILInjector InsertInPlaceAfterBranch(params CodeInstruction[] instructions) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown if (!IsValid) { throw new InvalidOperationException("Injector is invalid"); } List<Label> labels = Instruction.labels; Instruction = new CodeInstruction(Instruction); Instruction.labels.Clear(); this.instructions.InsertRange(index, instructions); Instruction.labels.AddRange(labels); if (matchEnd >= index) { matchEnd += instructions.Length; } return this; } public ILInjector InsertAfterBranch(params CodeInstruction[] instructions) { InsertInPlaceAfterBranch(instructions); index += instructions.Length; return this; } public ILInjector RemoveAllPreviousInstructions() { if (!IsValid) { throw new InvalidOperationException("Injector is invalid"); } instructions.RemoveRange(0, index); matchEnd -= index; if (matchEnd < 0) { matchEnd = 0; } index = 0; return this; } public ILInjector Remove(int count = 1) { if (!IsValid) { throw new InvalidOperationException("Injector is invalid"); } instructions.RemoveRange(index, count); if (matchEnd > index) { matchEnd = Math.Max(index, matchEnd - count); } return this; } public ILInjector RemoveLastMatch() { GetLastMatchRange(out var start, out var size); List<Label> labels = instructions[start].labels; instructions.RemoveRange(start, size); index = start; matchEnd = start; instructions[start].labels.AddRange(labels); return this; } public ILInjector ReplaceLastMatch(params CodeInstruction[] replacementInstructions) { if (replacementInstructions.Length == 0) { throw new ArgumentException("Cannot replace a match with an empty array."); } GetLastMatchRange(out var start, out var size); List<Label> labels = instructions[start].labels; instructions.RemoveRange(start, size); instructions.InsertRange(start, replacementInstructions); index = start; matchEnd = start + replacementInstructions.Length; instructions[start].labels.AddRange(labels); return this; } public List<CodeInstruction> ReleaseInstructions() { List<CodeInstruction> result = instructions; instructions = null; return result; } public ILInjector PrintContext(int context, string header = "") { if (!IsValid) { throw new InvalidOperationException("Injector is invalid (" + header + ")"); } StringBuilder stringBuilder = new StringBuilder(header); if (header.Length > 0) { stringBuilder.Append(':'); } stringBuilder.AppendLine(); GetLastMatchRangeAbsolute(out var start, out var end); int num = Math.Min(end + 1 + context, instructions.Count); for (int i = Math.Max(start - context, 0); i < num; i++) { if (end == -1 && i == index) { stringBuilder.Append("╶> "); } else { if (i >= start && i < end) { stringBuilder.Append("│"); } else { stringBuilder.Append(" "); } if (i == index) { stringBuilder.Append("╶> "); } else { stringBuilder.Append(" "); } } stringBuilder.AppendLine($"{i}: {instructions[i]}"); } Plugin.Instance.Logger.LogInfo((object)stringBuilder); return this; } public ILInjector PrintContext(string header = "") { return PrintContext(4, header); } } internal interface ILMatcher { bool Matches(CodeInstruction instruction); ILMatcher CaptureAs(out CodeInstruction variable) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Expected O, but got Unknown variable = new CodeInstruction(OpCodes.Nop, (object)null); return new InstructionCapturingMatcher(this, variable); } unsafe ILMatcher CaptureOperandAs<T>(out T operand) where T : unmanaged { operand = default(T); fixed (T* operand2 = &operand) { return new OperandCapturingMatcher<T>(this, operand2); } } static ILMatcher Not(ILMatcher matcher) { return new NotMatcher(matcher); } static ILMatcher Opcode(OpCode opcode) { return new OpcodeMatcher(opcode); } static ILMatcher Opcodes(params OpCode[] opcodes) { return new OpcodesMatcher(opcodes); } static ILMatcher OpcodeOperand(OpCode opcode, object operand) { return new OpcodeOperandMatcher(opcode, operand); } static ILMatcher Instruction(CodeInstruction instruction) { return new InstructionMatcher(instruction); } static ILMatcher Ldarg(int? arg = null) { return new LdargMatcher(arg); } static ILMatcher Ldloc(int? loc = null) { return new LdlocMatcher(loc); } static ILMatcher Stloc(int? loc = null) { return new StlocMatcher(loc); } static ILMatcher Ldc(int? value = null) { return new LdcI32Matcher(value); } static ILMatcher Branch() { return new BranchMatcher(); } static ILMatcher Ldfld(FieldInfo field, [CallerMemberName] string callerName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0) { if (field == null) { Plugin.Instance.Logger.LogWarning((object)$"Field passed to ILMatcher.Ldfld() was null at {sourceFilePath}#{sourceLineNumber} ({callerName})"); } return new OpcodeOperandMatcher(OpCodes.Ldfld, field); } static ILMatcher Ldsfld(FieldInfo field, [CallerMemberName] string callerName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0) { if (field == null) { Plugin.Instance.Logger.LogWarning((object)$"Field passed to ILMatcher.Ldsfld() was null at {sourceFilePath}#{sourceLineNumber} ({callerName})"); } return new OpcodeOperandMatcher(OpCodes.Ldsfld, field); } static ILMatcher Stfld(FieldInfo field, [CallerMemberName] string callerName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0) { if (field == null) { Plugin.Instance.Logger.LogWarning((object)$"Field passed to ILMatcher.Stfld() was null at {sourceFilePath}#{sourceLineNumber} ({callerName})"); } return new OpcodeOperandMatcher(OpCodes.Stfld, field); } static ILMatcher Stsfld(FieldInfo field, [CallerMemberName] string callerName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0) { if (field == null) { Plugin.Instance.Logger.LogWarning((object)$"Field passed to ILMatcher.Stsfld() was null at {sourceFilePath}#{sourceLineNumber} ({callerName})"); } return new OpcodeOperandMatcher(OpCodes.Stsfld, field); } static ILMatcher Callvirt(MethodBase method, [CallerMemberName] string callerName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0) { if (method == null) { Plugin.Instance.Logger.LogWarning((object)$"Method passed to ILMatcher.Callvirt() was null at {sourceFilePath}#{sourceLineNumber} ({callerName})"); } return OpcodeOperand(OpCodes.Callvirt, method); } static ILMatcher Call(MethodBase method, [CallerMemberName] string callerName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0) { if (method == null) { Plugin.Instance.Logger.LogWarning((object)$"Method passed to ILMatcher.Call() was null at {sourceFilePath}#{sourceLineNumber} ({callerName})"); } return OpcodeOperand(OpCodes.Call, method); } static ILMatcher Predicate(Func<CodeInstruction, bool> predicate) { return new PredicateMatcher(predicate); } static ILMatcher Predicate(Func<FieldInfo, bool> predicate) { return new PredicateMatcher((CodeInstruction insn) => insn.operand is FieldInfo arg && predicate(arg)); } } internal class NotMatcher : ILMatcher { private readonly ILMatcher matcher; public NotMatcher(ILMatcher matcher) { this.matcher = matcher; base..ctor(); } public bool Matches(CodeInstruction instruction) { return !matcher.Matches(instruction); } } internal class OpcodeMatcher : ILMatcher { private readonly OpCode opcode; public OpcodeMatcher(OpCode opcode) { this.opcode = opcode; base..ctor(); } public bool Matches(CodeInstruction instruction) { return instruction.opcode == opcode; } } internal class OpcodesMatcher : ILMatcher { private readonly OpCode[] opcodes; public OpcodesMatcher(OpCode[] opcodes) { this.opcodes = opcodes; base..ctor(); } public bool Matches(CodeInstruction instruction) { return opcodes.Contains(instruction.opcode); } } internal class OpcodeOperandMatcher : ILMatcher { private readonly OpCode opcode; private readonly object operand; public OpcodeOperandMatcher(OpCode opcode, object operand) { this.opcode = opcode; this.operand = operand; base..ctor(); } public bool Matches(CodeInstruction instruction) { if (instruction.opcode == opcode) { return instruction.operand == operand; } return false; } } internal class InstructionMatcher : ILMatcher { private readonly OpCode opcode = instruction.opcode; private readonly object operand = instruction.operand; private readonly Label[] labels = instruction.labels.ToArray(); public InstructionMatcher(CodeInstruction instruction) { } public bool Matches(CodeInstruction instruction) { if (instruction.opcode != opcode) { return false; } if (instruction.operand != operand) { return false; } if (instruction.labels.Count != labels.Length) { return false; } for (int i = 0; i < labels.Length; i++) { if (labels[i] != instruction.labels[i]) { return false; } } return true; } } internal class LdargMatcher : ILMatcher { private readonly int? arg; public LdargMatcher(int? arg) { this.arg = arg; base..ctor(); } public bool Matches(CodeInstruction instruction) { if (!arg.HasValue) { return instruction.GetLdargIndex().HasValue; } return instruction.GetLdargIndex() == arg; } } internal class LdlocMatcher : ILMatcher { private readonly int? loc; public LdlocMatcher(int? loc) { this.loc = loc; base..ctor(); } public bool Matches(CodeInstruction instruction) { if (!loc.HasValue) { return instruction.GetLdlocIndex().HasValue; } return instruction.GetLdlocIndex() == loc; } } internal class StlocMatcher : ILMatcher { private readonly int? loc; public StlocMatcher(int? loc) { this.loc = loc; base..ctor(); } public bool Matches(CodeInstruction instruction) { if (!loc.HasValue) { return instruction.GetStlocIndex().HasValue; } return instruction.GetStlocIndex() == loc; } } internal class LdcI32Matcher : ILMatcher { private readonly int? value; public LdcI32Matcher(int? value) { this.value = value; base..ctor(); } public bool Matches(CodeInstruction instruction) { if (!value.HasValue) { return instruction.GetLdcI32().HasValue; } return instruction.GetLdcI32() == value; } } internal class BranchMatcher : ILMatcher { public bool Matches(CodeInstruction instruction) { Label? label = default(Label?); return CodeInstructionExtensions.Branches(instruction, ref label); } } internal class PredicateMatcher : ILMatcher { private readonly Func<CodeInstruction, bool> predicate; public PredicateMatcher(Func<CodeInstruction, bool> predicate) { this.predicate = predicate; base..ctor(); } public bool Matches(CodeInstruction instruction) { return predicate(instruction); } } internal class InstructionCapturingMatcher : ILMatcher { private readonly ILMatcher matcher; private readonly CodeInstruction variable; public InstructionCapturingMatcher(ILMatcher matcher, CodeInstruction variable) { this.matcher = matcher; this.variable = variable; base..ctor(); } public bool Matches(CodeInstruction instruction) { bool num = matcher.Matches(instruction); if (num) { variable.opcode = instruction.opcode; variable.operand = instruction.operand; variable.blocks = instruction.blocks.ToList(); variable.labels = instruction.labels.ToList(); } return num; } } internal class OperandCapturingMatcher<T> : ILMatcher where T : unmanaged { private readonly ILMatcher matcher; private unsafe readonly T* operand; public unsafe OperandCapturingMatcher(ILMatcher matcher, T* operand) { this.matcher = matcher; this.operand = operand; base..ctor(); } public unsafe bool Matches(CodeInstruction instruction) { bool num = matcher.Matches(instruction); if (num) { *operand = (T)instruction.operand; } return num; } } internal static class InstructionUtilities { public static CodeInstruction MakeLdarg(int index) { //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Expected O, but got Unknown //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Expected O, but got Unknown //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Expected O, but got Unknown //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Expected O, but got Unknown //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Expected O, but got Unknown if (index < 256) { return (CodeInstruction)(index switch { 0 => (object)new CodeInstruction(OpCodes.Ldarg_0, (object)null), 1 => (object)new CodeInstruction(OpCodes.Ldarg_1, (object)null), 2 => (object)new CodeInstruction(OpCodes.Ldarg_2, (object)null), 3 => (object)new CodeInstruction(OpCodes.Ldarg_3, (object)null), _ => (object)new CodeInstruction(OpCodes.Ldarg_S, (object)index), }); } return new CodeInstruction(OpCodes.Ldarg, (object)index); } public static int PopCount(this CodeInstruction instruction) { if (instruction.opcode == OpCodes.Call || instruction.opcode == OpCodes.Callvirt) { MethodInfo obj = (MethodInfo)instruction.operand; int num = obj.GetParameters().Length; if (!obj.IsStatic) { num++; } return num; } if (instruction.opcode == OpCodes.Ret) { return 1; } return instruction.opcode.StackBehaviourPop switch { StackBehaviour.Pop0 => 0, StackBehaviour.Pop1 => 1, StackBehaviour.Pop1_pop1 => 2, StackBehaviour.Popi => 1, StackBehaviour.Popi_pop1 => 2, StackBehaviour.Popi_popi => 2, StackBehaviour.Popi_popi8 => 2, StackBehaviour.Popi_popi_popi => 3, StackBehaviour.Popi_popr4 => 2, StackBehaviour.Popi_popr8 => 2, StackBehaviour.Popref => 1, StackBehaviour.Popref_pop1 => 2, StackBehaviour.Popref_popi => 2, StackBehaviour.Popref_popi_popi => 3, StackBehaviour.Popref_popi_popi8 => 3, StackBehaviour.Popref_popi_popr4 => 3, StackBehaviour.Popref_popi_popr8 => 3, StackBehaviour.Popref_popi_popref => 3, StackBehaviour.Varpop => throw new NotImplementedException($"Variable pop on non-call instruction '{instruction}'"), StackBehaviour.Popref_popi_pop1 => 3, _ => throw new NotSupportedException($"StackBehaviourPop of {instruction.opcode.StackBehaviourPop} was not a pop for instruction '{instruction}'"), }; } public static int PushCount(this CodeInstruction instruction) { if (instruction.opcode == OpCodes.Call || instruction.opcode == OpCodes.Callvirt) { if (((MethodInfo)instruction.operand).ReturnType == typeof(void)) { return 0; } return 1; } return instruction.opcode.StackBehaviourPush switch { StackBehaviour.Push0 => 0, StackBehaviour.Push1 => 1, StackBehaviour.Push1_push1 => 2, StackBehaviour.Pushi => 1, StackBehaviour.Pushi8 => 1, StackBehaviour.Pushr4 => 1, StackBehaviour.Pushr8 => 1, StackBehaviour.Pushref => 1, StackBehaviour.Varpush => throw new NotImplementedException($"Variable push on non-call instruction '{instruction}'"), _ => throw new NotSupportedException($"StackBehaviourPush of {instruction.opcode.StackBehaviourPush} was not a push for instruction '{instruction}'"), }; } public static int? GetLdargIndex(this CodeInstruction instruction) { OpCode opcode = instruction.opcode; if (opcode == OpCodes.Ldarg_0) { return 0; } if (opcode == OpCodes.Ldarg_1) { return 1; } if (opcode == OpCodes.Ldarg_2) { return 2; } if (opcode == OpCodes.Ldarg_3) { return 3; } if (opcode == OpCodes.Ldarg || opcode == OpCodes.Ldarg_S) { return instruction.operand as int?; } return null; } public static int? GetLdlocIndex(this CodeInstruction instruction) { OpCode opcode = instruction.opcode; if (opcode == OpCodes.Ldloc_0) { return 0; } if (opcode == OpCodes.Ldloc_1) { return 1; } if (opcode == OpCodes.Ldloc_2) { return 2; } if (opcode == OpCodes.Ldloc_3) { return 3; } if (opcode == OpCodes.Ldloc || opcode == OpCodes.Ldloc_S) { return (instruction.operand as LocalBuilder)?.LocalIndex; } return null; } public static int? GetStlocIndex(this CodeInstruction instruction) { OpCode opcode = instruction.opcode; if (opcode == OpCodes.Stloc_0) { return 0; } if (opcode == OpCodes.Stloc_1) { return 1; } if (opcode == OpCodes.Stloc_2) { return 2; } if (opcode == OpCodes.Stloc_3) { return 3; } if (opcode == OpCodes.Stloc || opcode == OpCodes.Stloc_S) { return (instruction.operand as LocalBuilder)?.LocalIndex; } return null; } public static CodeInstruction LdlocToStloc(this CodeInstruction instruction) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Expected O, but got Unknown //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Expected O, but got Unknown //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Expected O, but got Unknown OpCode opcode = instruction.opcode; if (opcode == OpCodes.Ldloc_0) { return new CodeInstruction(OpCodes.Stloc_0, (object)null); } if (opcode == OpCodes.Ldloc_1) { return new CodeInstruction(OpCodes.Stloc_1, (object)null); } if (opcode == OpCodes.Ldloc_2) { return new CodeInstruction(OpCodes.Stloc_2, (object)null); } if (opcode == OpCodes.Ldloc_3) { return new CodeInstruction(OpCodes.Stloc_3, (object)null); } if (opcode == OpCodes.Ldloc || opcode == OpCodes.Ldloc_S) { return new CodeInstruction(OpCodes.Stloc, instruction.operand); } return null; } public static CodeInstruction StlocToLdloc(this CodeInstruction instruction) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Expected O, but got Unknown //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Expected O, but got Unknown //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Expected O, but got Unknown OpCode opcode = instruction.opcode; if (opcode == OpCodes.Stloc_0) { return new CodeInstruction(OpCodes.Ldloc_0, (object)null); } if (opcode == OpCodes.Stloc_1) { return new CodeInstruction(OpCodes.Ldloc_1, (object)null); } if (opcode == OpCodes.Stloc_2) { return new CodeInstruction(OpCodes.Ldloc_2, (object)null); } if (opcode == OpCodes.Stloc_3) { return new CodeInstruction(OpCodes.Ldloc_3, (object)null); } if (opcode == OpCodes.Stloc || opcode == OpCodes.Stloc_S) { return new CodeInstruction(OpCodes.Ldloc, instruction.operand); } return null; } public static int? GetLdcI32(this CodeInstruction instruction) { OpCode opcode = instruction.opcode; if (opcode == OpCodes.Ldc_I4_M1) { return -1; } if (opcode == OpCodes.Ldc_I4_0) { return 0; } if (opcode == OpCodes.Ldc_I4_1) { return 1; } if (opcode == OpCodes.Ldc_I4_2) { return 2; } if (opcode == OpCodes.Ldc_I4_3) { return 3; } if (opcode == OpCodes.Ldc_I4_4) { return 4; } if (opcode == OpCodes.Ldc_I4_5) { return 5; } if (opcode == OpCodes.Ldc_I4_6) { return 6; } if (opcode == OpCodes.Ldc_I4_7) { return 7; } if (opcode == OpCodes.Ldc_I4_8) { return 8; } if (opcode == OpCodes.Ldc_I4_S) { return instruction.operand as sbyte?; } if (opcode == OpCodes.Ldc_I4) { return instruction.operand as int?; } return null; } } } namespace TwoRadarMaps.Patches { internal static class Common { public static ILInjector ReplaceMainMapWithTerminalMap(this ILInjector injector) { //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Expected O, but got Unknown injector.GoToStart(); while (true) { injector.Find(ILMatcher.Call(Reflection.m_StartOfRound_Instance, "ReplaceMainMapWithTerminalMap", "E:\\Development\\Lethal Company\\Projects\\TwoRadarMaps\\TwoRadarMaps\\Patches\\Common.cs", 20), ILMatcher.Ldfld(Reflection.f_StartOfRound_mapScreen, "ReplaceMainMapWithTerminalMap", "E:\\Development\\Lethal Company\\Projects\\TwoRadarMaps\\TwoRadarMaps\\Patches\\Common.cs", 21)); if (!injector.IsValid) { break; } injector.ReplaceLastMatch(new CodeInstruction(OpCodes.Ldsfld, (object)Reflection.f_Plugin_terminalMapRenderer)); } return injector.GoToStart(); } internal static ILInjector InsertTerminalField(this ILInjector injector, CodeInstruction loadRenderer, FieldInfo vanillaStartOfRoundField, FieldInfo pluginField) { //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Expected O, but got Unknown //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Expected O, but got Unknown //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Expected O, but got Unknown //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Expected O, but got Unknown injector.GoToStart(); while (true) { injector.Find(ILMatcher.Call(Reflection.m_StartOfRound_Instance, "InsertTerminalField", "E:\\Development\\Lethal Company\\Projects\\TwoRadarMaps\\TwoRadarMaps\\Patches\\Common.cs", 44), ILMatcher.Ldfld(vanillaStartOfRoundField, "InsertTerminalField", "E:\\Development\\Lethal Company\\Projects\\TwoRadarMaps\\TwoRadarMaps\\Patches\\Common.cs", 45)); if (!injector.IsValid) { break; } injector.DefineLabel(out var label).Insert(loadRenderer, new CodeInstruction(OpCodes.Ldsfld, (object)Reflection.f_Plugin_terminalMapRenderer), new CodeInstruction(OpCodes.Beq_S, (object)label)).GoToMatchEnd() .AddLabel(out var label2) .Insert(new CodeInstruction(OpCodes.Br_S, (object)label2), CodeInstructionExtensions.WithLabels(new CodeInstruction(OpCodes.Ldsfld, (object)pluginField), new Label[1] { label })); } return injector.GoToStart(); } } [HarmonyPatch(typeof(ManualCameraRenderer))] internal static class PatchManualCameraRenderer { [CompilerGenerated] private sealed class <SyncOrderOfRadarBoostersInListPostfix>d__8 : IEnumerable<CodeInstruction>, IEnumerable, IEnumerator<CodeInstruction>, IEnumerator, IDisposable { private int <>1__state; private CodeInstruction <>2__current; private int <>l__initialThreadId; private IEnumerable<CodeInstruction> instructions; public IEnumerable<CodeInstruction> <>3__instructions; private IEnumerator<CodeInstruction> <>7__wrap1; CodeInstruction IEnumerator<CodeInstruction>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <SyncOrderOfRadarBoostersInListPostfix>d__8(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || (uint)(num - 1) <= 1u) { try { } finally { <>m__Finally1(); } } <>7__wrap1 = null; <>1__state = -2; } private bool MoveNext() { //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Expected O, but got Unknown try { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>7__wrap1 = instructions.GetEnumerator(); <>1__state = -3; break; case 1: <>1__state = -3; break; case 2: <>1__state = -3; break; } if (<>7__wrap1.MoveNext()) { CodeInstruction current = <>7__wrap1.Current; if (CodeInstructionExtensions.StoresField(current, Reflection.f_ManualCameraRenderer_radarTargets)) { <>2__current = new CodeInstruction(OpCodes.Call, (object)Reflection.GetMethod(typeof(PatchManualCameraRenderer), "ApplySortedTargets", BindingFlags.Static | BindingFlags.NonPublic, new Type[2] { typeof(ManualCameraRenderer), typeof(List<TransformAndName>) })); <>1__state = 1; return true; } <>2__current = current; <>1__state = 2; return true; } <>m__Finally1(); <>7__wrap1 = null; return false; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; if (<>7__wrap1 != null) { <>7__wrap1.Dispose(); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator<CodeInstruction> IEnumerable<CodeInstruction>.GetEnumerator() { <SyncOrderOfRadarBoostersInListPostfix>d__8 <SyncOrderOfRadarBoostersInListPostfix>d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; <SyncOrderOfRadarBoostersInListPostfix>d__ = this; } else { <SyncOrderOfRadarBoostersInListPostfix>d__ = new <SyncOrderOfRadarBoostersInListPostfix>d__8(0); } <SyncOrderOfRadarBoostersInListPostfix>d__.instructions = <>3__instructions; return <SyncOrderOfRadarBoostersInListPostfix>d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<CodeInstruction>)this).GetEnumerator(); } } [HarmonyPatch(/*Could not decode attribute arguments.*/)] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> updateMapTargetTranspiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown return new ILInjector(instructions, generator).InsertTerminalField(new CodeInstruction(OpCodes.Ldloc_1, (object)null), Reflection.f_StartOfRound_mapScreenPlayerName, Reflection.f_Plugin_terminalMapScreenPlayerName).ReleaseInstructions(); } [HarmonyPatch("MapCameraFocusOnPosition")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> MapCameraFocusOnPositionTranspiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown return new ILInjector(instructions, generator).InsertTerminalField(new CodeInstruction(OpCodes.Ldarg_0, (object)null), Reflection.f_StartOfRound_radarCanvas, Reflection.f_Plugin_terminalMapScreenUICanvas).ReleaseInstructions(); } [HarmonyPatch("ChangeNameOfTargetTransform")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> ChangeNameOfTargetTransformTranspiler(IEnumerable<CodeInstruction> instructions) { //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Expected O, but got Unknown CodeInstruction variable; ILInjector iLInjector = new ILInjector(instructions).Find(ILMatcher.Ldarg(0), ILMatcher.Ldfld(Reflection.f_ManualCameraRenderer_radarTargets, "ChangeNameOfTargetTransformTranspiler", "E:\\Development\\Lethal Company\\Projects\\TwoRadarMaps\\TwoRadarMaps\\Patches\\PatchManualCameraRenderer.cs", 44), ILMatcher.Ldloc().CaptureAs(out variable), ILMatcher.Callvirt(Reflection.m_List_TransformAndName_get_Item, "ChangeNameOfTargetTransformTranspiler", "E:\\Development\\Lethal Company\\Projects\\TwoRadarMaps\\TwoRadarMaps\\Patches\\PatchManualCameraRenderer.cs", 46), ILMatcher.Ldarg(), ILMatcher.Stfld(Reflection.f_TransformAndName_name, "ChangeNameOfTargetTransformTranspiler", "E:\\Development\\Lethal Company\\Projects\\TwoRadarMaps\\TwoRadarMaps\\Patches\\PatchManualCameraRenderer.cs", 48)); if (!iLInjector.IsValid) { Plugin.Instance.Logger.LogError((object)"Could not find setting of a radar target name in ManualCameraRenderer.ChangeNameOfTargetTransform()."); return instructions; } return iLInjector.Insert(variable, new CodeInstruction(OpCodes.Call, (object)Reflection.GetMethod(typeof(PatchManualCameraRenderer), "OnTargetNameChanged", BindingFlags.Static | BindingFlags.NonPublic, new Type[1] { typeof(int) }))).ReleaseInstructions(); } private static void ApplyTargetNameChange(ManualCameraRenderer mapRenderer, int targetIndex) { if (targetIndex == mapRenderer.targetTransformIndex) { Plugin.StartTargetTransition(mapRenderer, mapRenderer.targetTransformIndex); } } private static void OnTargetNameChanged(int targetIndex) { ApplyTargetNameChange(StartOfRound.Instance.mapScreen, targetIndex); ApplyTargetNameChange(Plugin.TerminalMapRenderer, targetIndex); } [HarmonyPatch("RemoveTargetFromRadar")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> RemoveTargetFromRadarTranspiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator) { //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Expected O, but got Unknown //IL_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_01bb: Expected O, but got Unknown CodeInstruction variable; ILInjector iLInjector = new ILInjector(instructions, generator).Find(ILMatcher.Ldarg(0), ILMatcher.Ldfld(Reflection.f_ManualCameraRenderer_radarTargets, "RemoveTargetFromRadarTranspiler", "E:\\Development\\Lethal Company\\Projects\\TwoRadarMaps\\TwoRadarMaps\\Patches\\PatchManualCameraRenderer.cs", 100), ILMatcher.Ldloc().CaptureAs(out variable), ILMatcher.Callvirt(typeof(List<TransformAndName>).GetMethod("RemoveAt", new Type[1] { typeof(int) }), "RemoveTargetFromRadarTranspiler", "E:\\Development\\Lethal Company\\Projects\\TwoRadarMaps\\TwoRadarMaps\\Patches\\PatchManualCameraRenderer.cs", 102)); if (!iLInjector.IsValid) { Plugin.Instance.Logger.LogError((object)"Failed to find the removal of a target from the list in ManualCameraRenderer.RemoveTargetFromRadar."); return instructions; } iLInjector.Find(ILMatcher.Ldarg(0), ILMatcher.Ldfld(typeof(ManualCameraRenderer).GetField("targetTransformIndex"), "RemoveTargetFromRadarTranspiler", "E:\\Development\\Lethal Company\\Projects\\TwoRadarMaps\\TwoRadarMaps\\Patches\\PatchManualCameraRenderer.cs", 114), ILMatcher.Ldarg(0), ILMatcher.Ldfld(Reflection.f_ManualCameraRenderer_radarTargets, "RemoveTargetFromRadarTranspiler", "E:\\Development\\Lethal Company\\Projects\\TwoRadarMaps\\TwoRadarMaps\\Patches\\PatchManualCameraRenderer.cs", 116), ILMatcher.Callvirt(typeof(List<TransformAndName>).GetMethod("get_Count"), "RemoveTargetFromRadarTranspiler", "E:\\Development\\Lethal Company\\Projects\\TwoRadarMaps\\TwoRadarMaps\\Patches\\PatchManualCameraRenderer.cs", 117), ILMatcher.Opcode(OpCodes.Blt).CaptureOperandAs<Label>(out var operand)).FindLabel(operand); if (!iLInjector.IsValid) { Plugin.Instance.Logger.LogError((object)"No check for out-of-bounds target was found in ManualCameraRenderer.RemoveTargetFromRadar."); return instructions; } return iLInjector.ReplaceLastMatch(new CodeInstruction(variable), new CodeInstruction(OpCodes.Call, (object)Reflection.GetMethod(typeof(PatchManualCameraRenderer), "RadarTargetWasRemoved", BindingFlags.Static | BindingFlags.NonPublic, new Type[1] { typeof(int) }))).ReleaseInstructions(); } private static void FixUpRadarTargetRemovalFor(ManualCameraRenderer mapRenderer, int removedIndex) { bool flag = removedIndex <= mapRenderer.targetTransformIndex; if (mapRenderer.targetTransformIndex >= mapRenderer.radarTargets.Count) { mapRenderer.targetTransformIndex--; } int nextValidTarget = Plugin.GetNextValidTarget(mapRenderer.radarTargets, mapRenderer.targetTransformIndex); if (nextValidTarget == -1) { mapRenderer.targetedPlayer = null; } else if (flag) { Plugin.StartTargetTransition(mapRenderer, nextValidTarget); } } private static void RadarTargetWasRemoved(int removedIndex) { FixUpRadarTargetRemovalFor(StartOfRound.Instance.mapScreen, removedIndex); FixUpRadarTargetRemovalFor(Plugin.TerminalMapRenderer, removedIndex); } [IteratorStateMachine(typeof(<SyncOrderOfRadarBoostersInListPostfix>d__8))] [HarmonyPatch("SyncOrderOfRadarBoostersInList")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> SyncOrderOfRadarBoostersInListPostfix(IEnumerable<CodeInstruction> instructions) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <SyncOrderOfRadarBoostersInListPostfix>d__8(-2) { <>3__instructions = instructions }; } private static void OnTargetListResorted(ManualCameraRenderer mapRenderer, List<TransformAndName> sortedTargets) { int targetTransformIndex = mapRenderer.targetTransformIndex; Transform transform = mapRenderer.radarTargets[targetTransformIndex].transform; if (mapRenderer.radarTargets[targetTransformIndex] == sortedTargets[targetTransformIndex]) { return; } for (int i = 0; i < sortedTargets.Count; i++) { if ((Object)(object)sortedTargets[i].transform == (Object)(object)transform) { Plugin.SetTargetIndex(mapRenderer, i); return; } } mapRenderer.radarTargets = sortedTargets; int nextValidTarget = Plugin.GetNextValidTarget(sortedTargets, targetTransformIndex); if (nextValidTarget != -1) { Plugin.StartTargetTransition(mapRenderer, nextValidTarget); } } private static void ApplySortedTargets(ManualCameraRenderer _, List<TransformAndName> sortedTargets) { OnTargetListResorted(StartOfRound.Instance.mapScreen, sortedTargets); OnTargetListResorted(Plugin.TerminalMapRenderer, sortedTargets); StartOfRound.Instance.mapScreen.radarTargets = sortedTargets; Plugin.TerminalMapRenderer.radarTargets = sortedTargets; } [HarmonyPatch("MeetsCameraEnabledConditions")] [HarmonyPrefix] private static bool MeetsCameraEnabledConditionsPrefix(ManualCameraRenderer __instance, ref bool __result) { if ((Object)(object)__instance != (Object)(object)Plugin.TerminalMapRenderer) { return true; } RawImage terminalImage = Plugin.Terminal.terminalImage; __result = ((Behaviour)terminalImage).isActiveAndEnabled && (Object)(object)terminalImage.texture == (Object)(object)__instance.cam.targetTexture; return false; } } [HarmonyPatch(typeof(ShipTeleporter))] internal static class PatchShipTeleporter { public static readonly MethodInfo m_NetworkManager_get_IsListening = typeof(NetworkManager).GetMethod("get_IsListening"); public static readonly MethodInfo m_WriteCurrentTarget = Reflection.GetMethod(typeof(PatchShipTeleporter), "WriteCurrentTargetIndex", BindingFlags.Static | BindingFlags.NonPublic, new Type[1] { typeof(FastBufferWriter) }); public static readonly MethodInfo m_ReadTargetIndexAndSet = Reflection.GetMethod(typeof(PatchShipTeleporter), "ReadTargetIndexAndSet", BindingFlags.Static | BindingFlags.NonPublic, new Type[1] { typeof(FastBufferReader) }); public static readonly MethodInfo m_Plugin_SetTargetIndex = Reflection.GetMethod(typeof(Plugin), "SetTargetIndex", BindingFlags.Static | BindingFlags.NonPublic, new Type[2] { typeof(ManualCameraRenderer), typeof(int) }); public static readonly MethodInfo m_ShipTeleporter_PressTeleportButtonServerRpcHandler = Reflection.GetMethod(typeof(ShipTeleporter), "__rpc_handler_389447712", BindingFlags.Static | BindingFlags.NonPublic, new Type[3] { typeof(NetworkBehaviour), typeof(FastBufferReader), typeof(__RpcParams) }); public static readonly MethodInfo m_ShipTeleporter_PressTeleportButtonClientRpc = typeof(ShipTeleporter).GetMethod("PressTeleportButtonClientRpc", Array.Empty<Type>()); private static readonly MethodInfo m_TranspileRPCReceiveHAndlerToSetTarget = Reflection.GetMethod(typeof(PatchShipTeleporter), "TranspileRPCReceiveHandlerToSetTarget", BindingFlags.Static | BindingFlags.NonPublic, new Type[3] { typeof(IEnumerable<CodeInstruction>), typeof(ILGenerator), typeof(MethodBase) }); private static readonly List<uint> rpcMessageIDs = new List<uint>(2); [HarmonyPostfix] [HarmonyPatch("OnEnable")] private static void OnEnablePostfix(ShipTeleporter __instance) { if (!__instance.isInverseTeleporter) { Plugin.Teleporter = __instance; } } [HarmonyPostfix] [HarmonyPatch("OnDisable")] private static void OnDisablePostfix(ShipTeleporter __instance) { if (!((Object)(object)__instance != (Object)(object)Plugin.Teleporter)) { Plugin.Teleporter = null; } } [HarmonyTranspiler] [HarmonyPatch("PressTeleportButtonServerRpc")] [HarmonyPatch("PressTeleportButtonClientRpc")] private static IEnumerable<CodeInstruction> TranspileRPCSendToWriteTargetIndex(IEnumerable<CodeInstruction> instructions, MethodBase method) { //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Expected O, but got Unknown int operand; CodeInstruction variable; ILInjector iLInjector = new ILInjector(instructions).Find(ILMatcher.Ldarg(0), ILMatcher.Ldc().CaptureOperandAs<int>(out operand), ILMatcher.Ldloc(), ILMatcher.Ldc(), ILMatcher.Predicate((CodeInstruction insn) => insn.opcode == OpCodes.Call && ((MethodBase)insn.operand).Name.StartsWith("__beginSend")), ILMatcher.Stloc().CaptureAs(out variable)).GoToMatchEnd(); if (!iLInjector.IsValid) { Plugin.Instance.Logger.LogError((object)("No call to __beginSend[..]() was found in " + method.DeclaringType.Name + "." + method.Name + "().")); return instructions; } iLInjector.Insert(variable.StlocToLdloc(), new CodeInstruction(OpCodes.Call, (object)m_WriteCurrentTarget)); rpcMessageIDs.Add((uint)operand); return iLInjector.ReleaseInstructions(); } [HarmonyPostfix] [HarmonyPatch("InitializeRPCS_ShipTeleporter")] private static void InitializeRPCS_ShipTeleporterPostfix() { PatchRPCReceiveHandlers(Plugin.Harmony); } private static void WriteCurrentTargetIndex(FastBufferWriter writer) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) ((FastBufferWriter)(ref writer)).WriteValue<int>(ref StartOfRound.Instance.mapScreen.targetTransformIndex, default(ForPrimitives)); } private static void PatchRPCReceiveHandlers(Harmony harmony) { foreach (uint rpcMessageID in rpcMessageIDs) { if (!NetworkManager.__rpc_func_table.TryGetValue(rpcMessageID, out var value)) { Plugin.Instance.Logger.LogError((object)$"Failed to find RPC message handler with ID {rpcMessageID}."); Plugin.Instance.Logger.LogError((object)"This may cause errors when using the ship teleporter."); } else { harmony.CreateProcessor((MethodBase)((Delegate)(object)value).GetMethodInfo()).AddTranspiler(m_TranspileRPCReceiveHAndlerToSetTarget).Patch(); } } } private static int ReadTargetIndexAndSet(FastBufferReader reader) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) ManualCameraRenderer mapScreen = StartOfRound.Instance.mapScreen; int targetTransformIndex = mapScreen.targetTransformIndex; int targetIndex = default(int); ((FastBufferReader)(ref reader)).ReadValue<int>(ref targetIndex, default(ForPrimitives)); Plugin.SetTargetIndex(mapScreen, targetIndex); return targetTransformIndex; } private static IEnumerable<CodeInstruction> TranspileRPCReceiveHandlerToSetTarget(IEnumerable<CodeInstruction> instructions, ILGenerator generator, MethodBase method) { //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Expected O, but got Unknown //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Expected O, but got Unknown //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Expected O, but got Unknown //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Expected O, but got Unknown //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_018f: Expected O, but got Unknown //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Expected O, but got Unknown //IL_01a9: Unknown result type (might be due to invalid IL or missing references) //IL_01af: Expected O, but got Unknown Label operand; ILInjector iLInjector = new ILInjector(instructions).Find(ILMatcher.Ldloc(), ILMatcher.Callvirt(m_NetworkManager_get_IsListening, "TranspileRPCReceiveHandlerToSetTarget", "E:\\Development\\Lethal Company\\Projects\\TwoRadarMaps\\TwoRadarMaps\\Patches\\PatchShipTeleporter.cs", 130), ILMatcher.Opcode(OpCodes.Brtrue).CaptureOperandAs<Label>(out operand)).FindLabel(operand); if (!iLInjector.IsValid) { Plugin.Instance.Logger.LogError((object)("No access of NetworkManager.IsListening was found in " + method.DeclaringType.Name + "." + method.Name + "().")); return instructions; } LocalBuilder localBuilder = generator.DeclareLocal(typeof(int)); iLInjector.InsertAfterBranch(new CodeInstruction(OpCodes.Ldarg_1, (object)null), new CodeInstruction(OpCodes.Call, (object)m_ReadTargetIndexAndSet), new CodeInstruction(OpCodes.Stloc, (object)localBuilder)).Find(ILMatcher.Opcode(OpCodes.Ret)); if (!iLInjector.IsValid) { Plugin.Instance.Logger.LogError((object)("No return instruction was found in " + method.DeclaringType.Name + "." + method.Name + "().")); return instructions; } return iLInjector.Insert(new CodeInstruction(OpCodes.Call, (object)Reflection.m_StartOfRound_Instance), new CodeInstruction(OpCodes.Ldfld, (object)Reflection.f_StartOfRound_mapScreen), new CodeInstruction(OpCodes.Ldloc, (object)localBuilder), new CodeInstruction(OpCodes.Call, (object)m_Plugin_SetTargetIndex)).ReleaseInstructions(); } } [HarmonyPatch(typeof(Terminal))] internal static class PatchTerminal { [HarmonyPostfix] [HarmonyPatch("Awake")] public static void AwakePostfix(Terminal __instance) { Plugin.Terminal = __instance; TerminalCommands.Initialize(); } [HarmonyPrefix] [HarmonyPatch("Start")] private static void StartPrefix() { //IL_0437: Unknown result type (might be due to invalid IL or missing references) //IL_0441: Expected O, but got Unknown //IL_0507: Unknown result type (might be due to invalid IL or missing references) //IL_050c: Unknown result type (might be due to invalid IL or missing references) //IL_0517: Unknown result type (might be due to invalid IL or missing references) //IL_051d: Unknown result type (might be due to invalid IL or missing references) //IL_052c: Expected O, but got Unknown //IL_0560: Unknown result type (might be due to invalid IL or missing references) //IL_0565: Unknown result type (might be due to invalid IL or missing references) //IL_056d: Unknown result type (might be due to invalid IL or missing references) //IL_0572: Unknown result type (might be due to invalid IL or missing references) GameObject gameObject = ((Component)Plugin.Terminal).gameObject; GameObject val = GameObject.Find("Systems/GameSystems/ItemSystems"); if ((Object)(object)val == (Object)null) { Plugin.Instance.Logger.LogError((object)"Could not find the ItemSystems object."); return; } Transform obj = val.transform.Find("MapCamera"); GameObject val2 = ((obj != null) ? ((Component)obj).gameObject : null); if ((Object)(object)val2 == (Object)null) { Plugin.Instance.Logger.LogError((object)"Could not find the default map camera."); return; } ManualCameraRenderer val3 = StartOfRound.Instance?.mapScreen; if ((Object)(object)val3 == (Object)null) { Plugin.Instance.Logger.LogError((object)"Default map camera renderer is null."); return; } Transform obj2 = val.transform.Find("MapScreenUI"); GameObject val4 = ((obj2 != null) ? ((Component)obj2).gameObject : null); if ((Object)(object)val4 == (Object)null) { Plugin.Instance.Logger.LogError((object)"Could not find the map screen UI."); return; } GameObject val5 = Object.Instantiate<GameObject>(val2, val.transform, false); Camera val6 = ((val5 != null) ? val5.GetComponent<Camera>() : null); if ((Object)(object)val6 == (Object)null) { Plugin.Instance.Logger.LogError((object)"Failed to clone the default map camera."); return; } ((Object)val5).name = "TerminalMapCamera"; GameObject val7 = Object.Instantiate<GameObject>(val4, val.transform, false); Canvas val8 = ((val7 != null) ? val7.GetComponent<Canvas>() : null); val8.worldCamera = val6; if ((Object)(object)val8 == (Object)null) { Plugin.Instance.Logger.LogError((object)"Failed to clone the default map's UI."); return; } ((Object)val7).name = "TerminalMapScreenUI"; Transform obj3 = val7.transform.Find("PlanetVideoReel"); GameObject val9 = ((obj3 != null) ? ((Component)obj3).gameObject : null); Transform obj4 = val7.transform.Find("PlanetDescription"); GameObject val10 = ((obj4 != null) ? ((Component)obj4).gameObject : null); if ((Object)(object)val9 == (Object)null || (Object)(object)val10 == (Object)null) { Plugin.Instance.Logger.LogError((object)"Failed to delete duplicated planet description."); return; } Object.Destroy((Object)(object)val9); Object.Destroy((Object)(object)val10); Transform obj5 = val7.transform.Find(((Object)val3.shipArrowUI).name); GameObject val11 = ((obj5 != null) ? ((Component)obj5).gameObject : null); Transform val12 = val11.transform.Find(((Object)val3.shipArrowPointer).name); if ((Object)(object)val11 == (Object)null || (Object)(object)val12 == (Object)null) { Plugin.Instance.Logger.LogError((object)"Failed to get cloned ship arrow pointer."); return; } Transform obj6 = val7.transform.Find(((Object)val3.LostSignalUI).name); GameObject val13 = ((obj6 != null) ? ((Component)obj6).gameObject : null); if ((Object)(object)val13 == (Object)null) { Plugin.Instance.Logger.LogError((object)"Failed to get cloned signal lost text UI."); return; } Transform val14 = val7.transform.Find("MonitoringPlayerUIContainer"); Transform obj7 = val14.Find("PlayerBeingMonitored"); TextMeshProUGUI val15 = ((obj7 != null) ? ((Component)obj7).GetComponent<TextMeshProUGUI>() : null); if ((Object)(object)val15 == (Object)null) { Plugin.Instance.Logger.LogError((object)"Failed to get cloned player name text UI."); return; } ((Behaviour)val15).enabled = true; Transform obj8 = val14.Find(((Object)val3.headMountedCamUI).name); RawImage val16 = ((obj8 != null) ? ((Component)obj8).GetComponent<RawImage>() : null); if ((Object)(object)val16 == (Object)null) { Plugin.Instance.Logger.LogError((object)"Failed to get cloned head mounted cam view UI."); return; } ((Behaviour)val16).enabled = true; Transform obj9 = val14.Find(((Object)val3.localPlayerPlaceholder).name); Image val17 = ((obj9 != null) ? ((Component)obj9).GetComponent<Image>() : null); if ((Object)(object)val17 == (Object)null) { Plugin.Instance.Logger.LogError((object)"Failed to get the local player placeholder head mounted cam view UI."); return; } ((Behaviour)val17).enabled = true; Transform obj10 = val14.Find(((Object)val3.compassRose).name); Image val18 = ((obj10 != null) ? ((Component)obj10).GetComponent<Image>() : null); if ((Object)(object)val18 == (Object)null) { Plugin.Instance.Logger.LogError((object)"Failed to get cloned compass UI."); return; } ((Behaviour)val18).enabled = true; Animator componentInChildren = val5.GetComponentInChildren<Animator>(); if ((Object)(object)componentInChildren == (Object)null) { Plugin.Instance.Logger.LogError((object)"Failed to find new map flash animation."); return; } Camera val19 = Object.Instantiate<Camera>(val3.headMountedCam, val.transform, false); if ((Object)(object)val19 == (Object)null) { Plugin.Instance.Logger.LogError((object)"Failed to create a head mounted camera for the terminal map."); return; } ((Object)val19).name = "TerminalHeadMountedCamera"; val19.targetTexture = new RenderTexture(val3.headMountedCam.targetTexture); val16.texture = (Texture)(object)val19.targetTexture; LineRenderer val20 = Object.Instantiate<LineRenderer>(val3.lineFromRadarTargetToExit, val.transform, false); if ((Object)(object)val20 == (Object)null) { Plugin.Instance.Logger.LogError((object)"Failed to create a new map exit line for the terminal."); return; } ((Object)val20).name = "TerminalMapExitLine"; GameObject obj11 = GameObject.Find("Environment/HangarShip/Terminal"); if ((Object)(object)((obj11 != null) ? obj11.GetComponentInChildren<MeshRenderer>() : null) == (Object)null) { Plugin.Instance.Logger.LogError((object)"Failed to find terminal object mesh."); return; } ManualCameraRenderer val21 = gameObject.AddComponent<ManualCameraRenderer>(); val21.cameraNearPlane = val3.cameraNearPlane; val21.cameraFarPlane = val3.cameraFarPlane; val21.cam = val6; val21.mapCamera = val6; val21.cam.targetTexture = new RenderTexture(val3.cam.targetTexture) { name = "TerminalMapTexture", filterMode = Plugin.TextureFiltering.Value }; val21.mapCameraStationaryUI = val3.mapCameraStationaryUI; val21.shipArrowUI = val11; val21.shipArrowPointer = val12; val21.compassRose = val18; val21.headMountedCam = val19; val21.headMountedCamPositionOffset = val3.headMountedCamPositionOffset; val21.headMountedCamRotationOffset = val3.headMountedCamRotationOffset; val21.headMountedCamUI = val16; val21.localPlayerPlaceholder = val17; val21.LostSignalUI = val13; val21.mapCameraAnimator = componentInChildren; val21.lineFromRadarTargetToExit = val20; val21.targetedPlayer = val3.targetedPlayer; TerminalNode val22 = ((IEnumerable<CompatibleNoun>)((IEnumerable<TerminalKeyword>)Plugin.Terminal.terminalNodes.allKeywords).FirstOrDefault((Func<TerminalKeyword, bool>)((TerminalKeyword keyword) => keyword.word == "view"))?.compatibleNouns).FirstOrDefault((Func<CompatibleNoun, bool>)((CompatibleNoun noun) => noun.noun.word == "monitor"))?.result; if ((Object)(object)val22 != (Object)null) { val22.displayTexture = (Texture)(object)val21.cam.targetTexture; Plugin.Instance.Logger.LogInfo((object)("Terminal node '" + ((Object)val22).name + "' will now use a separate texture.")); } Plugin.TerminalMapRenderer = val21; Plugin.TerminalMapScreenUICanvas = val8; Plugin.TerminalMapScreenPlayerName = val15; val3.SyncOrderOfRadarBoostersInList(); Plugin.UpdateZoomFactors(); } [HarmonyTranspiler] [HarmonyPatch("RunTerminalEvents")] [HarmonyPatch("ParsePlayerSentence")] [HarmonyPatch("CheckForPlayerNameCommand")] private static IEnumerable<CodeInstruction> TranspileRunTerminalEvents(IEnumerable<CodeInstruction> instructions) { return new ILInjector(instructions).ReplaceMainMapWithTerminalMap().ReleaseInstructions(); } [HarmonyPrefix] [HarmonyPatch("RunTerminalEvents")] private static bool RunTerminalEventsPrefix(TerminalNode __0) { return TerminalCommands.ProcessNode(__0); } } internal static class PatchVanillaBugs { [HarmonyFinalizer] [HarmonyPatch(typeof(PlayerControllerB), "ConnectClientToPlayerObject")] [HarmonyAfter(new string[] { "Zaggy1024.OpenBodyCams" })] private static void ConnectClientToPlayerObjectPostfix() { UpdateMonitoredPlayerNames(); OpenBodyCamsCompatibility.InitializeAtStartOfGame(); } [HarmonyTranspiler] [HarmonyPatch(typeof(PlayerControllerB), "SendNewPlayerValuesClientRpc")] private static IEnumerable<CodeInstruction> SendNewPlayerValuesClientRpcTranspiler(IEnumerable<CodeInstruction> instructions) { //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Expected O, but got Unknown //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Expected O, but got Unknown //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Expected O, but got Unknown //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Expected O, but got Unknown //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Expected O, but got Unknown //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Expected O, but got Unknown //IL_01bf: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Expected O, but got Unknown CodeInstruction variable; CodeInstruction variable2; ILInjector iLInjector = new ILInjector(instructions).Find(ILMatcher.Call(Reflection.m_StartOfRound_Instance, "SendNewPlayerValuesClientRpcTranspiler", "E:\\Development\\Lethal Company\\Projects\\TwoRadarMaps\\TwoRadarMaps\\Patches\\PatchVanillaBugs.cs", 55), ILMatcher.Ldfld(Reflection.f_StartOfRound_mapScreen, "SendNewPlayerValuesClientRpcTranspiler", "E:\\Development\\Lethal Company\\Projects\\TwoRadarMaps\\TwoRadarMaps\\Patches\\PatchVanillaBugs.cs", 56), ILMatcher.Ldfld(Reflection.f_ManualCameraRenderer_radarTargets, "SendNewPlayerValuesClientRpcTranspiler", "E:\\Development\\Lethal Company\\Projects\\TwoRadarMaps\\TwoRadarMaps\\Patches\\PatchVanillaBugs.cs", 57), ILMatcher.Ldloc().CaptureAs(out variable), ILMatcher.Callvirt(Reflection.m_List_TransformAndName_get_Item, "SendNewPlayerValuesClientRpcTranspiler", "E:\\Development\\Lethal Company\\Projects\\TwoRadarMaps\\TwoRadarMaps\\Patches\\PatchVanillaBugs.cs", 59), ILMatcher.Ldloc().CaptureAs(out variable2), ILMatcher.Stfld(Reflection.f_TransformAndName_name, "SendNewPlayerValuesClientRpcTranspiler", "E:\\Development\\Lethal Company\\Projects\\TwoRadarMaps\\TwoRadarMaps\\Patches\\PatchVanillaBugs.cs", 61)); if (!iLInjector.IsValid) { if (!Chainloader.PluginInfos.ContainsKey("mattymatty.LobbyControl")) { Plugin.Instance.Logger.LogWarning((object)"Failed to patch SendNewPlayerValuesClientRpc to set the correct transform index's name."); Plugin.Instance.Logger.LogWarning((object)"LobbyControl is not installed, but another mod may have fixed this vanilla bug."); } return instructions; } return iLInjector.ReplaceLastMatch(new CodeInstruction(OpCodes.Call, (object)Reflection.m_StartOfRound_Instance), new CodeInstruction(OpCodes.Ldfld, (object)Reflection.f_StartOfRound_mapScreen), new CodeInstruction(OpCodes.Call, (object)Reflection.m_StartOfRound_Instance), new CodeInstruction(OpCodes.Ldfld, (object)Reflection.f_StartOfRound_allPlayerScripts), variable, new CodeInstruction(OpCodes.Ldelem, (object)typeof(PlayerControllerB)), new CodeInstruction(OpCodes.Call, (object)Reflection.m_Component_Transform), variable2, new CodeInstruction(OpCodes.Call, (object)typeof(ManualCameraRenderer).GetMethod("ChangeNameOfTargetTransform", new Type[2] { typeof(Transform), typeof(string) }))).ReleaseInstructions(); } private static void UpdateMonitoredPlayerNames() { Plugin.EnsureAllMapRenderersHaveValidTargets(); } [HarmonyPatch(typeof(StartOfRound), "OnClientConnect")] [HarmonyTranspiler] public static IEnumerable<CodeInstruction> OnClientConnectTranspiler(IEnumerable<CodeInstruction> instructions) { //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Expected O, but got Unknown ILInjector iLInjector = new ILInjector(instructions).Find(ILMatcher.Call(typeof(StartOfRound).GetMethod("OnPlayerConnectedClientRpc", BindingFlags.Instance | BindingFlags.NonPublic), "OnClientConnectTranspiler", "E:\\Development\\Lethal Company\\Projects\\TwoRadarMaps\\TwoRadarMaps\\Patches\\PatchVanillaBugs.cs", 101)).GoToMatchEnd(); if (!iLInjector.IsValid) { Plugin.Instance.Logger.LogError((object)"Failed to find the call to OnPlayerConnectedClientRpc in StartOfRound.OnClientConnect()."); return instructions; } return iLInjector.Insert(new CodeInstruction(OpCodes.Call, (object)typeof(PatchVanillaBugs).GetMethod("SynchronizeMapTargetsToNewClient", BindingFlags.Static | BindingFlags.NonPublic))).ReleaseInstructions(); } private static void SynchronizeMapTargetsToNewClient() { StartOfRound.Instance.mapScreen.SwitchRadarTargetClientRpc(StartOfRound.Instance.mapScreen.targetTransformIndex); Plugin.TerminalMapRenderer.SwitchRadarTargetClientRpc(Plugin.TerminalMapRenderer.targetTransformIndex); } } public static class Reflection { public static readonly MethodInfo m_Component_Transform = typeof(Component).GetMethod("get_transform"); public static readonly MethodInfo m_StartOfRound_Instance = typeof(StartOfRound).GetMethod("get_Instance"); public static readonly FieldInfo f_StartOfRound_allPlayerScripts = typeof(StartOfRound).GetField("allPlayerScripts"); public static readonly FieldInfo f_StartOfRound_mapScreen = typeof(StartOfRound).GetField("mapScreen"); public static readonly FieldInfo f_StartOfRound_mapScreenPlayerName = typeof(StartOfRound).GetField("mapScreenPlayerName"); public static readonly FieldInfo f_StartOfRound_radarCanvas = typeof(StartOfRound).GetField("radarCanvas"); public static readonly FieldInfo f_ManualCameraRenderer_radarTargets = typeof(ManualCameraRenderer).GetField("radarTargets"); public static readonly MethodInfo m_List_TransformAndName_get_Item = typeof(List<TransformAndName>).GetMethod("get_Item", new Type[1] { typeof(int) }); public static readonly FieldInfo f_Plugin_terminalMapRenderer = typeof(Plugin).GetField("TerminalMapRenderer"); public static readonly FieldInfo f_Plugin_terminalMapScreenUICanvas = typeof(Plugin).GetField("TerminalMapScreenUICanvas"); public static readonly FieldInfo f_Plugin_terminalMapScreenPlayerName = typeof(Plugin).GetField("TerminalMapScreenPlayerName"); public static readonly FieldInfo f_TransformAndName_name = typeof(TransformAndName).GetField("name"); public static readonly MethodInfo m_UnityEngine_Object_op_Equality = typeof(Object).GetMethod("op_Equality", new Type[2] { typeof(Object), typeof(Object) }); public static MethodInfo GetMethod(this Type type, string name, BindingFlags bindingFlags, Type[] parameters) { return type.GetMethod(name, bindingFlags, null, parameters, null); } } } namespace TwoRadarMaps.Compatibility { internal static class EnhancedRadarBoosterCompatibility { internal const string ENHANCED_RADAR_BOOSTER_MOD_ID = "MrHydralisk.EnhancedRadarBooster"; internal const string IMMERSIVE_COMPANY_MOD_ID = "ImmersiveCompany"; private static MethodInfo m_MapCameraFocusOnPositionPostfixTranspiler; private static MethodInfo m_Camera_set_orthographicSize; private static bool patchAppliedSuccessfully; internal static void Initialize(Harmony harmony) { m_MapCameraFocusOnPositionPostfixTranspiler = Reflection.GetMethod(typeof(EnhancedRadarBoosterCompatibility), "MapCameraFocusOnPositionPostfixTranspiler", BindingFlags.Static | BindingFlags.NonPublic, new Type[3] { typeof(IEnumerable<CodeInstruction>), typeof(ILGenerator), typeof(MethodBase) }); if (m_MapCameraFocusOnPositionPostfixTranspiler == null) { Plugin.Instance.Logger.LogError((object)"MapCameraFocusOnPositionPostfixTranspiler was not found."); Plugin.Instance.Logger.LogError((object)"Patches for MrHydralisk.EnhancedRadarBooster and ImmersiveCompany cannot be applied."); return; } m_Camera_set_orthographicSize = typeof(Camera).GetMethod("set_orthographicSize"); if (Chainloader.PluginInfos.ContainsKey("MrHydralisk.EnhancedRadarBooster")) { InitializeForEnhancedRadarBooster(harmony); } if (Chainloader.PluginInfos.ContainsKey("ImmersiveCompany")) { InitializeForImmersiveCompany(harmony); } } [MethodImpl(MethodImplOptions.NoInlining)] private static void InitializeForEnhancedRadarBooster(Harmony harmony) { MethodInfo method = typeof(HarmonyPatches).GetMethod("MCR_MapCameraFocusOnPosition_Postfix", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(ManualCameraRenderer) }, null); if (method == null) { Plugin.Instance.Logger.LogError((object)"MrHydralisk.EnhancedRadarBooster is present, but MCR_MapCameraFocusOnPosition_Postfix was not found."); return; } try { harmony.CreateProcessor((MethodBase)method).AddTranspiler(m_MapCameraFocusOnPositionPostfixTranspiler).Patch(); } catch (Exception ex) { Plugin.Instance.Logger.LogError((object)"Failed to transpile MrHydralisk.EnhancedRadarBooster's MCR_MapCameraFocusOnPosition_Postfix"); Plugin.Instance.Logger.LogError((object)ex); } if (patchAppliedSuccessfully) { Plugin.Instance.Logger.LogInfo((object)"Finished patching EnhancedRadarBooster for compatibility with the zoom command."); } else { Plugin.Instance.Logger.LogError((object)"Failed to patch EnhancedRadarBooster for compatibility with the zoom command."); } } [MethodImpl(MethodImplOptions.NoInlining)] private static void InitializeForImmersiveCompany(Harmony harmony) { MethodInfo method = typeof(ManualCameraRendererPatch).GetMethod("MapCameraFocusPatch", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(ManualCameraRenderer) }, null); if (method == null) { Plugin.Instance.Logger.LogError((object)"ImmersiveCompany is present, but MapCameraFocusPatch was not found."); return; } try { harmony.CreateProcessor((MethodBase)method).AddTranspiler(m_MapCameraFocusOnPositionPostfixTranspiler).Patch(); } catch (Exception ex) { Plugin.Instance.Logger.LogError((object)"Failed to transpile ImmersiveCompany's MapCameraFocusPatch"); Plugin.Instance.Logger.LogError((object)ex); } if (patchAppliedSuccessfully) { Plugin.Instance.Logger.LogInfo((object)"Finished patching ImmersiveCompany for compatibility with the zoom command."); } else { Plugin.Instance.Logger.LogError((object)"Failed to patch ImmersiveCompany for compatibility with the zoom command."); } } private static IEnumerable<CodeInstruction> MapCameraFocusOnPositionPostfixTranspiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator, MethodBase method) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Expected O, but got Unknown //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Expected O, but got Unknown //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Expected O, but got Unknown //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Expected O, but got Unknown //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Expected O, but got Unknown //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Expected O, but got Unknown //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Expected O, but got Unknown ILInjector iLInjector = new ILInjector(instructions, generator).InsertTerminalField(new CodeInstruction(OpCodes.Ldarg_0, (object)null), Reflection.f_StartOfRound_radarCanvas, Reflection.f_Plugin_terminalMapScreenUICanvas); patchAppliedSuccessfully = false; while (true) { iLInjector.Find(ILMatcher.Callvirt(m_Camera_set_orthographicSize, "MapCameraFocusOnPositionPostfixTranspiler", "E:\\Development\\Lethal Company\\Projects\\TwoRadarMaps\\TwoRadarMaps\\Compatibility\\EnhancedRadarBoosterCompatibility.cs", 123)); if (!iLInjector.IsValid) { break; } iLInjector.Forward(1).AddLabel(out var label).Back(1) .GoToPush(1) .AddLabel(out var label2) .Insert(new CodeInstruction(OpCodes.Ldsfld, (object)typeof(TerminalCommands).GetField("CycleZoomNode")), new CodeInstruction(OpCodes.Brfalse_S, (object)label2), new CodeInstruction(OpCodes.Ldarg_0, (object)null), new CodeInstruction(OpCodes.Call, (object)Reflection.m_StartOfRound_Instance), new CodeInstruction(OpCodes.Ldfld, (object)Reflection.f_StartOfRound_mapScreen), new CodeInstruction(OpCodes.Beq_S, (object)label2), new CodeInstruction(OpCodes.Br_S, (object)label)) .Find(ILMatcher.Callvirt(