Decompiled source of ShipTeleportKey v1.5.3

ShipTeleportKey.dll

Decompiled an hour ago
using System;
using System.Collections;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("ShipTeleportKey")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+caff75b709da63c082e01784e214d55304ad9240")]
[assembly: AssemblyProduct("ShipTeleportKey")]
[assembly: AssemblyTitle("ShipTeleportKey")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[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 ShipTeleportKey
{
	[BepInPlugin("dp991.ShipTeleportKey", "ShipTeleportKey", "1.5.4")]
	public class ShipTeleportKeyPlugin : BaseUnityPlugin
	{
		public const string Guid = "dp991.ShipTeleportKey";

		public const string Name = "ShipTeleportKey";

		public const string Version = "1.5.4";

		internal static ManualLogSource Log;

		internal static ConfigEntry<Key> TeleportKey;

		internal static ConfigEntry<bool> KeepItems;

		internal static ConfigEntry<float> InverseCooldown;

		private void Awake()
		{
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Expected O, but got Unknown
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			TeleportKey = ((BaseUnityPlugin)this).Config.Bind<Key>("General", "TeleportKey", (Key)97, "Кнопка, по которой телепорт корабля забирает тебя на корабль.");
			KeepItems = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "KeepItemsOnTeleport", true, "Не выбрасывать предметы из рук при телепортации (и обычным, и инверсным телепортом).");
			InverseCooldown = ((BaseUnityPlugin)this).Config.Bind<float>("General", "InverseTeleportCooldownSeconds", 10f, "Перезарядка инверсного телепорта (который кидает в помещение) в секундах. В игре по умолчанию 210.");
			Harmony val = new Harmony("dp991.ShipTeleportKey");
			val.PatchAll(typeof(KeepItemsPatches));
			val.PatchAll(typeof(CooldownPatches));
			val.PatchAll(typeof(TeleportTargetPatches));
			val.PatchAll(typeof(NetworkPrefabPatch2));
			GameObject val2 = new GameObject("ShipTeleportKeyRunner")
			{
				hideFlags = (HideFlags)61
			};
			Object.DontDestroyOnLoad((Object)val2);
			val2.AddComponent<TeleportRunner>();
			Log.LogInfo((object)string.Format("{0} {1} загружен. Кнопка телепорта: {2}", "ShipTeleportKey", "1.5.4", TeleportKey.Value));
		}
	}
	internal class TeleportRunner : MonoBehaviour
	{
		private static readonly FieldInfo CooldownField = typeof(ShipTeleporter).GetField("cooldownTime", BindingFlags.Instance | BindingFlags.NonPublic);

		private bool _teleportInProgress;

		private bool _firstUpdateLogged;

		private bool _keyWasPressed;

		private float _lastPressTime = -10f;

		private InputAction _teleportAction;

		private void Update()
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Expected O, but got Unknown
			if (!_firstUpdateLogged)
			{
				_firstUpdateLogged = true;
				ShipTeleportKeyPlugin.Log.LogInfo((object)$"Update работает. Клавиатура обнаружена: {Keyboard.current != null}.");
			}
			Keyboard current = Keyboard.current;
			if (current == null)
			{
				return;
			}
			Key value = ShipTeleportKeyPlugin.TeleportKey.Value;
			if (_teleportAction == null)
			{
				string path = ((InputControl)current[value]).path;
				_teleportAction = new InputAction("ShipTeleportKey.Teleport", (InputActionType)1, path, (string)null, (string)null, (string)null);
				_teleportAction.performed += delegate
				{
					OnTeleportKeyPressed("InputAction");
				};
				_teleportAction.Enable();
				ShipTeleportKeyPlugin.Log.LogInfo((object)("Кнопка привязана через InputAction: " + path));
			}
			bool isPressed = ((ButtonControl)current[value]).isPressed;
			if (isPressed && !_keyWasPressed)
			{
				OnTeleportKeyPressed("опрос isPressed");
			}
			_keyWasPressed = isPressed;
		}

		private void OnDisable()
		{
			ShipTeleportKeyPlugin.Log.LogWarning((object)"TeleportRunner отключён (OnDisable) — кнопка перестанет работать!");
		}

		private void OnDestroy()
		{
			ShipTeleportKeyPlugin.Log.LogWarning((object)"TeleportRunner уничтожен (OnDestroy) — кнопка перестанет работать!");
			InputAction teleportAction = _teleportAction;
			if (teleportAction != null)
			{
				teleportAction.Disable();
			}
			InputAction teleportAction2 = _teleportAction;
			if (teleportAction2 != null)
			{
				teleportAction2.Dispose();
			}
		}

		private void OnTeleportKeyPressed(string source)
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			if (!(Time.unscaledTime - _lastPressTime < 0.3f))
			{
				_lastPressTime = Time.unscaledTime;
				if (!_teleportInProgress)
				{
					ShipTeleportKeyPlugin.Log.LogInfo((object)$"Нажата кнопка {ShipTeleportKeyPlugin.TeleportKey.Value} (источник: {source}) — пробую телепортироваться.");
					TryTeleportSelf();
				}
			}
		}

		private void TryTeleportSelf()
		{
			ManualLogSource log = ShipTeleportKeyPlugin.Log;
			StartOfRound instance = StartOfRound.Instance;
			if ((Object)(object)instance == (Object)null)
			{
				log.LogInfo((object)"StartOfRound.Instance == null (мы в главном меню?) — отмена.");
				return;
			}
			PlayerControllerB localPlayerController = instance.localPlayerController;
			if ((Object)(object)localPlayerController == (Object)null)
			{
				log.LogInfo((object)"localPlayerController == null — отмена.");
				return;
			}
			if (localPlayerController.isTypingChat || localPlayerController.inTerminalMenu)
			{
				log.LogInfo((object)$"Игрок занят (чат: {localPlayerController.isTypingChat}, терминал: {localPlayerController.inTerminalMenu}) — отмена.");
				return;
			}
			ShipTeleporter val = FindShipTeleporter();
			if ((Object)(object)val == (Object)null)
			{
				log.LogInfo((object)"Телепорт на корабле не найден — телепортация невозможна.");
				return;
			}
			float num = ((CooldownField != null) ? ((float)CooldownField.GetValue(val)) : 0f);
			if (num > 0f)
			{
				log.LogInfo((object)$"Телепорт на перезарядке: ещё {num:F0} сек.");
				HUDManager instance2 = HUDManager.Instance;
				if (instance2 != null)
				{
					instance2.DisplayTip("Телепорт", $"Перезарядка: ещё {(int)num} сек.", false, false, "LC_Tip1");
				}
				return;
			}
			ManualCameraRenderer mapScreen = instance.mapScreen;
			if ((Object)(object)mapScreen == (Object)null)
			{
				log.LogInfo((object)"mapScreen == null — отмена.");
				return;
			}
			bool flag = instance.inShipPhase && !localPlayerController.isInsideFactory;
			int num2 = (flag ? mapScreen.targetTransformIndex : FindPlayerRadarIndex(mapScreen, localPlayerController));
			if (num2 < 0 || num2 >= mapScreen.radarTargets.Count)
			{
				log.LogWarning((object)"Не удалось определить цель на радаре — отмена.");
				return;
			}
			string arg = mapScreen.radarTargets[num2]?.name ?? "?";
			log.LogInfo((object)(flag ? $"На корабле — цель [{num2}]: {arg}." : $"На луне — цель (я) [{num2}]: {arg}."));
			if (!flag && (mapScreen.targetTransformIndex != num2 || (Object)(object)mapScreen.targetedPlayer == (Object)null || (Object)(object)mapScreen.targetedPlayer != (Object)(object)localPlayerController))
			{
				((MonoBehaviour)this).StartCoroutine(SyncRadarAndPress(mapScreen, num2, val));
			}
			else
			{
				PressTeleportWithLockedTarget(mapScreen, num2, val);
			}
		}

		private static int FindPlayerRadarIndex(ManualCameraRenderer mapScreen, PlayerControllerB player)
		{
			for (int i = 0; i < mapScreen.radarTargets.Count; i++)
			{
				TransformAndName val = mapScreen.radarTargets[i];
				if (val != null && (Object)(object)val.transform == (Object)(object)((Component)player).transform)
				{
					return i;
				}
			}
			return -1;
		}

		private static void PressTeleportWithLockedTarget(ManualCameraRenderer mapScreen, int targetIndex, ShipTeleporter teleporter)
		{
			TeleportTargetPatches.ApplyRadarTarget(mapScreen, targetIndex);
			TeleportTargetPatches.LockedTargetIndex = targetIndex;
			try
			{
				ShipTeleportKeyPlugin.Log.LogInfo((object)"Нажимаю кнопку телепорта.");
				teleporter.PressTeleportButtonOnLocalClient();
			}
			catch (Exception arg)
			{
				ShipTeleportKeyPlugin.Log.LogError((object)$"Ошибка при нажатии телепорта: {arg}");
			}
			finally
			{
				TeleportTargetPatches.LockedTargetIndex = -1;
			}
		}

		private IEnumerator SyncRadarAndPress(ManualCameraRenderer mapScreen, int targetIndex, ShipTeleporter teleporter)
		{
			_teleportInProgress = true;
			try
			{
				ShipTeleportKeyPlugin.Log.LogInfo((object)$"Синхронизирую радар на индекс {targetIndex}...");
				mapScreen.SwitchRadarTargetAndSync(targetIndex);
				yield return (object)new WaitForSecondsRealtime(0.35f);
				PressTeleportWithLockedTarget(mapScreen, targetIndex, teleporter);
			}
			finally
			{
				_teleportInProgress = false;
			}
		}

		private static ShipTeleporter FindShipTeleporter()
		{
			ShipTeleporter[] array = Object.FindObjectsOfType<ShipTeleporter>();
			foreach (ShipTeleporter val in array)
			{
				if (!val.isInverseTeleporter)
				{
					return val;
				}
			}
			return null;
		}
	}
	internal static class TeleportTargetPatches
	{
		internal static int LockedTargetIndex = -1;

		internal static void ApplyRadarTarget(ManualCameraRenderer mapScreen, int index)
		{
			if (!((Object)(object)mapScreen == (Object)null) && index >= 0 && index < mapScreen.radarTargets.Count)
			{
				TransformAndName val = mapScreen.radarTargets[index];
				if (!((Object)(object)val?.transform == (Object)null))
				{
					mapScreen.targetTransformIndex = index;
					mapScreen.targetedPlayer = ((Component)val.transform).GetComponentInParent<PlayerControllerB>();
				}
			}
		}

		[HarmonyPatch(typeof(ShipTeleporter), "PressTeleportButtonClientRpc")]
		[HarmonyPrefix]
		private static void LockTargetBeforeBeamUp(ShipTeleporter __instance)
		{
			if (!__instance.isInverseTeleporter)
			{
				ManualCameraRenderer val = StartOfRound.Instance?.mapScreen;
				if (!((Object)(object)val == (Object)null))
				{
					int index = ((LockedTargetIndex >= 0) ? LockedTargetIndex : val.targetTransformIndex);
					ApplyRadarTarget(val, index);
				}
			}
		}
	}
	internal static class KeepItemsPatches
	{
		private static bool _inverseTeleportInProgress;

		private static bool IsLocalPlayer(PlayerControllerB player)
		{
			if ((Object)(object)GameNetworkManager.Instance != (Object)null)
			{
				return (Object)(object)player == (Object)(object)GameNetworkManager.Instance.localPlayerController;
			}
			return false;
		}

		[HarmonyPatch(typeof(PlayerControllerB), "DropAllHeldItemsAndSync")]
		[HarmonyPrefix]
		private static bool SkipDropOnBeamUp(PlayerControllerB __instance)
		{
			if (ShipTeleportKeyPlugin.KeepItems.Value && __instance.shipTeleporterId == 1 && IsLocalPlayer(__instance))
			{
				ShipTeleportKeyPlugin.Log.LogInfo((object)"Телепорт на корабль: оставляю предметы в руках.");
				return false;
			}
			return true;
		}

		[HarmonyPatch(typeof(ShipTeleporter), "TeleportPlayerOutWithInverseTeleporter")]
		[HarmonyPrefix]
		private static void InverseTeleportStarted()
		{
			_inverseTeleportInProgress = true;
		}

		[HarmonyPatch(typeof(ShipTeleporter), "TeleportPlayerOutWithInverseTeleporter")]
		[HarmonyFinalizer]
		private static void InverseTeleportFinished()
		{
			_inverseTeleportInProgress = false;
		}

		[HarmonyPatch(typeof(PlayerControllerB), "DropAllHeldItems")]
		[HarmonyPrefix]
		private static bool SkipDropOnInverseTeleport(PlayerControllerB __instance)
		{
			if (ShipTeleportKeyPlugin.KeepItems.Value && _inverseTeleportInProgress && IsLocalPlayer(__instance))
			{
				ShipTeleportKeyPlugin.Log.LogInfo((object)"Телепорт с корабля: оставляю предметы в руках.");
				return false;
			}
			return true;
		}
	}
	internal static class CooldownPatches
	{
		private static readonly FieldInfo CooldownTimeField = typeof(ShipTeleporter).GetField("cooldownTime", BindingFlags.Instance | BindingFlags.NonPublic);

		[HarmonyPatch(typeof(ShipTeleporter), "Awake")]
		[HarmonyPostfix]
		private static void ReduceInverseCooldown(ShipTeleporter __instance)
		{
			if (__instance.isInverseTeleporter)
			{
				float num = (__instance.cooldownAmount = Mathf.Max(0f, ShipTeleportKeyPlugin.InverseCooldown.Value));
				if (CooldownTimeField != null && (float)CooldownTimeField.GetValue(__instance) > num)
				{
					CooldownTimeField.SetValue(__instance, num);
				}
				ShipTeleportKeyPlugin.Log.LogInfo((object)$"Перезарядка инверсного телепорта установлена: {num} сек.");
			}
		}
	}
	[HarmonyPatch(typeof(NetworkManager))]
	internal static class NetworkPrefabPatch2
	{
		private static readonly string MOD_GUID = "dp991.ShipTeleportKey";

		[HarmonyPostfix]
		[HarmonyPatch("SetSingleton")]
		private static void RegisterPrefab()
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Expected O, but got Unknown
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(MOD_GUID + " Prefab");
			((Object)val).hideFlags = (HideFlags)(((Object)val).hideFlags | 0x3D);
			Object.DontDestroyOnLoad((Object)(object)val);
			NetworkObject obj = val.AddComponent<NetworkObject>();
			typeof(NetworkObject).GetField("GlobalObjectIdHash", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(obj, GetHash(MOD_GUID));
			NetworkManager.Singleton.PrefabHandler.AddNetworkPrefab(val);
			static uint GetHash(string value)
			{
				return value?.Aggregate(17u, (uint current, char c) => (current * 31) ^ c) ?? 0;
			}
		}
	}
}