Please disclose if your mod was created primarily using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of TwoRadarMaps v1.6.4
TwoRadarMaps.dll
Decompiled 6 months 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.7")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("3.0.7.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.4")] [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.4"; 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)); PatchShipTeleporter.Apply(); RenderPipelineManager.beginCameraRendering += BeforeCameraRendering; OpenBodyCamsCompatibility.Initialize(); EnhancedRadarBoosterCompatibility.Initialize(); } 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.4"; } 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_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) GameObject contourMap = StartOfRound.Instance.mapScreen.contourMap; if (!((Object)(object)contourMap == (Object)null)) { if ((Object)(object)map.targetedPlayer == (Object)null && ((Component)map.headMountedCamTarget).transform.position.y <= -80f) { contourMap.SetActive(false); return; } if ((Object)(object)map.targetedPlayer != (Object)null && map.targetedPlayer.isInsideFactory) { contourMap.SetActive(false); return; } contourMap.SetActive(true); 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")] [HarmonyPostfix] private static void MeetsCameraEnabledConditionsPostfix(ManualCameraRenderer __instance, ref bool __result) { if (!((Object)(object)__instance != (Object)(object)Plugin.TerminalMapRenderer) && __result) { RawImage terminalImage = Plugin.Terminal.terminalImage; __result = ((Behaviour)terminalImage).isActiveAndEnabled && (Object)(object)terminalImage.texture == (Object)(object)__instance.cam.targetTexture; } } } [HarmonyPatch(typeof(ShipTeleporter))] internal static class PatchShipTeleporter { private static readonly List<uint> rpcMessageIDs = new List<uint>(2); private static bool useOldRPCHandlerTable = false; internal static void Apply() { Plugin.Harmony.PatchAll(typeof(PatchShipTeleporter)); MethodInfo method = typeof(ShipTeleporter).GetMethod("__initializeRpcs", BindingFlags.Instance | BindingFlags.NonPublic); if (method == null) { method = typeof(ShipTeleporter).GetMethod("InitializeRPCS_ShipTeleporter", BindingFlags.Static | BindingFlags.NonPublic); useOldRPCHandlerTable = true; } Plugin.Harmony.CreateProcessor((MethodBase)method).AddPostfix(typeof(PatchShipTeleporter).GetMethod("PatchRPCReceiveHandlers", BindingFlags.Static | BindingFlags.NonPublic)).Patch(); } private static bool TryGetRPCHandler(Type type, uint hash, out Delegate handler) { if (useOldRPCHandlerTable) { handler = null; if (!NetworkManager.__rpc_func_table.TryGetValue(hash, out var value)) { return false; } handler = (Delegate)(object)value; return true; } return TryGetRPCHandlerNew(type, hash, out handler); } [MethodImpl(MethodImplOptions.NoInlining)] private static bool TryGetRPCHandlerNew(Type type, uint hash, out Delegate handler) { handler = null; if (!NetworkBehaviour.__rpc_func_table.TryGetValue(type, out var value)) { return false; } if (!value.TryGetValue(hash, out var value2)) { return false; } handler = (Delegate)(object)value2; return true; } private static void PatchRPCReceiveHandlers() { MethodInfo method = typeof(PatchShipTeleporter).GetMethod("TranspileRPCReceiveHandlerToSetTarget", BindingFlags.Static | BindingFlags.NonPublic); foreach (uint rpcMessageID in rpcMessageIDs) { if (!TryGetRPCHandler(typeof(ShipTeleporter), rpcMessageID, out var handler)) { 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 { Plugin.Harmony.CreateProcessor((MethodBase)handler.GetMethodInfo()).AddTranspiler(method).Patch(); } } } [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_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0125: 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)typeof(PatchShipTeleporter).GetMethod("WriteCurrentTargetIndex", BindingFlags.Static | BindingFlags.NonPublic))); rpcMessageIDs.Add((uint)operand); return iLInjector.ReleaseInstructions(); } 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 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_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Expected O, but got Unknown //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Expected O, but got Unknown //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Expected O, but got Unknown //IL_019c: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Expected O, but got Unknown //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01b4: Expected O, but got Unknown //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Expected O, but got Unknown //IL_01df: Unknown result type (might be due to invalid IL or missing references) //IL_01e5: Expected O, but got Unknown Label operand; ILInjector iLInjector = new ILInjector(instructions).Find(ILMatcher.Ldloc(), ILMatcher.Callvirt(typeof(NetworkManager).GetProperty("IsListening").GetMethod, "TranspileRPCReceiveHandlerToSetTarget", "E:\\Development\\Lethal Company\\Projects\\TwoRadarMaps\\TwoRadarMaps\\Patches\\PatchShipTeleporter.cs", 160), 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)typeof(PatchShipTeleporter).GetMethod("ReadTargetIndexAndSet", BindingFlags.Static | BindingFlags.NonPublic)), 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)typeof(Plugin).GetMethod("SetTargetIndex", BindingFlags.Static | BindingFlags.NonPublic))).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() { 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(Plugin.Harmony); } if (Chainloader.PluginInfos.ContainsKey("ImmersiveCompany")) { InitializeForImmersiveCompany(Plugin.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(m_Camera_set_orthographicSize, "MapCameraFocusOnPositionPos