using System; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using GameNetcodeStuff; using HarmonyLib; using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("WarpBack")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("WarpBack")] [assembly: AssemblyCopyright("Copyright © 2026")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("a2cbf801-c072-46d1-86f2-e780de2bc74d")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("1.0.0.0")] namespace WarpBack; [BepInPlugin("azumi.warpback", "WarpBack", "1.0.0")] public class WarpBackPlugin : BaseUnityPlugin { internal static WarpBackPlugin Instance; internal static ManualLogSource Log; private Harmony harmony; internal static ConfigEntry InitialPositionWarpKey; internal static ConfigEntry SavePositionKey; internal static ConfigEntry LoadPositionWarpKey; internal static ConfigEntry TeleporterKey; private static Vector3 savedPosition; private static Quaternion savedRotation; private static bool hasSavedPosition; private static float lastWarpPressTime; private static float lastSavePositionPressTime; private static float lastWarpBackPressTime; private static float lastTeleporterPressTime; private const float InputCooldown = 0.2f; private void Awake() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) Instance = this; Log = ((BaseUnityPlugin)this).Logger; harmony = new Harmony("azumi.warpback"); harmony.PatchAll(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"WarpBack loaded."); InitialPositionWarpKey = ((BaseUnityPlugin)this).Config.Bind("Controls", "Initial Position Warp Key", (Key)97, "Key used to warp to initial ship position."); SavePositionKey = ((BaseUnityPlugin)this).Config.Bind("Controls", "Save Position Key", (Key)98, "Key used to save the current player position."); LoadPositionWarpKey = ((BaseUnityPlugin)this).Config.Bind("Controls", "Load Position Warp Key", (Key)99, "Key used to warp to the saved position, or the initial ship position if no saved position exists."); TeleporterKey = ((BaseUnityPlugin)this).Config.Bind("Controls", "Remote Teleporter Key", (Key)100, "Key used to remotely press the ship teleporter button."); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"Initial Position Warp Key: {InitialPositionWarpKey.Value}"); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"Save Position Key: {SavePositionKey.Value}"); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"Load Position Warp Key: {LoadPositionWarpKey.Value}"); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"Remote Teleporter Key: {TeleporterKey.Value}"); } internal static void CheckInput() { if (Keyboard.current != null) { CheckWarpInput(); CheckSavePositionInput(); CheckWarpBackInput(); CheckTeleporterInput(); } } private static void CheckWarpInput() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Invalid comparison between Unknown and I4 //IL_001b: 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) Key value = InitialPositionWarpKey.Value; if ((int)value != 0) { ButtonControl val = (ButtonControl)(object)Keyboard.current[value]; if (val != null && val.wasPressedThisFrame && !(Time.time - lastWarpPressTime < 0.2f)) { lastWarpPressTime = Time.time; Log.LogInfo((object)$"Initial position warp key pressed: {value}"); TryWarpLocalPlayer(); } } } private static void CheckSavePositionInput() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Invalid comparison between Unknown and I4 //IL_001b: 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) Key value = SavePositionKey.Value; if ((int)value != 0) { ButtonControl val = (ButtonControl)(object)Keyboard.current[value]; if (val != null && val.wasPressedThisFrame && !(Time.time - lastSavePositionPressTime < 0.2f)) { lastSavePositionPressTime = Time.time; Log.LogInfo((object)$"Save position key pressed: {value}"); TrySavePosition(); } } } private static void CheckWarpBackInput() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Invalid comparison between Unknown and I4 //IL_001b: 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) Key value = LoadPositionWarpKey.Value; if ((int)value != 0) { ButtonControl val = (ButtonControl)(object)Keyboard.current[value]; if (val != null && val.wasPressedThisFrame && !(Time.time - lastWarpBackPressTime < 0.2f)) { lastWarpBackPressTime = Time.time; Log.LogInfo((object)$"Load position warp key pressed: {value}"); TryWarpBack(); } } } private static void CheckTeleporterInput() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Invalid comparison between Unknown and I4 //IL_001b: 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) Key value = TeleporterKey.Value; if ((int)value != 0) { ButtonControl val = (ButtonControl)(object)Keyboard.current[value]; if (val != null && val.wasPressedThisFrame && !(Time.time - lastTeleporterPressTime < 0.2f)) { lastTeleporterPressTime = Time.time; Log.LogInfo((object)$"Remote teleporter key pressed: {value}"); TryRemoteTeleporter(); } } } public static void TrySavePosition() { //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)StartOfRound.Instance == (Object)null) { ShowNotification("WarpBack", "Unable to access the current game state."); return; } PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if ((Object)(object)val == (Object)null) { ShowNotification("WarpBack", "Unable to find the local player."); } else if (CanUseWarpFunctions(val)) { if (val.isPlayerDead) { ShowNotification("WarpBack", "You cannot save your position while dead."); return; } savedPosition = ((Component)val).transform.position; savedRotation = ((Component)val).transform.rotation; hasSavedPosition = true; Log.LogInfo((object)($"Saved position: {savedPosition} / " + $"rotation: {((Quaternion)(ref savedRotation)).eulerAngles}")); ShowNotification("WarpBack", "Position saved successfully.\n" + $"X: {savedPosition.x:F1} " + $"Y: {savedPosition.y:F1} " + $"Z: {savedPosition.z:F1}"); } } public static void TryWarpBack() { //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: Unknown result type (might be due to invalid IL or missing references) //IL_0200: Unknown result type (might be due to invalid IL or missing references) //IL_0215: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_01ca: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)StartOfRound.Instance == (Object)null) { ShowNotification("WarpBack", "Unable to access the current game state."); return; } PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if ((Object)(object)val == (Object)null) { ShowNotification("WarpBack", "Unable to find the local player."); } else { if (!CanUseWarpFunctions(val)) { return; } if (val.isPlayerDead) { ShowNotification("WarpBack", "You cannot warp while dead."); return; } Vector3 position; if (hasSavedPosition) { position = savedPosition; Log.LogInfo((object)("LoadPositionWarp: Saved position found. " + $"Warping player {val.playerClientId} " + $"to saved position {position}")); } else { Transform shipSpawnPoint = GetShipSpawnPoint(); if ((Object)(object)shipSpawnPoint == (Object)null) { Log.LogWarning((object)"LoadPositionWarp: No saved position and ship spawn point was not found."); ShowNotification("WarpBack", "No saved position and the initial ship position could not be found."); return; } position = shipSpawnPoint.position; Log.LogInfo((object)("LoadPositionWarp: No saved position. " + $"Warping player {val.playerClientId} " + $"to initial ship position {position}")); } val.TeleportPlayer(position, false, 0f, false, true); val.ResetPlayerBloodObjects(true); val.isInElevator = true; val.isInHangarShipRoom = true; val.isInsideFactory = false; ShowNotification("WarpBack", hasSavedPosition ? ("Warped to the saved position.\n" + $"X: {position.x:F1} " + $"Y: {position.y:F1} " + $"Z: {position.z:F1}") : ("No saved position.\nWarped to the initial ship position.\n" + $"X: {position.x:F1} " + $"Y: {position.y:F1} " + $"Z: {position.z:F1}")); } } public static void TryRemoteTeleporter() { if ((Object)(object)StartOfRound.Instance == (Object)null) { ShowNotification("WarpBack", "Unable to access the current game state."); return; } PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if ((Object)(object)val == (Object)null) { ShowNotification("WarpBack", "Unable to find the local player."); } else { if (!CanUseWarpFunctions(val)) { return; } if (val.isPlayerDead) { ShowNotification("WarpBack", "You cannot use the teleporter while dead."); return; } ShipTeleporter[] array = Object.FindObjectsOfType(); if (array == null || array.Length == 0) { Log.LogInfo((object)"Remote teleporter blocked: no ShipTeleporter found."); ShowNotification("WarpBack", "No teleporter was found."); return; } ShipTeleporter val2 = null; for (int i = 0; i < array.Length; i++) { if (!((Object)(object)array[i] == (Object)null) && !array[i].isInverseTeleporter) { val2 = array[i]; break; } } if ((Object)(object)val2 == (Object)null) { Log.LogInfo((object)"Remote teleporter blocked: normal teleporter not found."); ShowNotification("WarpBack", "No normal teleporter is available."); return; } if ((Object)(object)val2.buttonTrigger != (Object)null && !val2.buttonTrigger.interactable) { Log.LogInfo((object)("Remote teleporter blocked: teleporter is on cooldown. " + $"Teleporter ID: {val2.teleporterId}")); ShowNotification("WarpBack", "The teleporter is currently on cooldown."); return; } if ((Object)(object)StartOfRound.Instance.mapScreen == (Object)null) { Log.LogWarning((object)"Remote teleporter blocked: map screen not found."); ShowNotification("WarpBack", "Unable to access the ship monitor."); return; } if (StartOfRound.Instance.allPlayerScripts == null || StartOfRound.Instance.allPlayerScripts.Length == 0) { Log.LogWarning((object)"Remote teleporter blocked: player list not found."); ShowNotification("WarpBack", "Unable to access the player list."); return; } int num = -1; for (int j = 0; j < StartOfRound.Instance.allPlayerScripts.Length; j++) { if ((Object)(object)StartOfRound.Instance.allPlayerScripts[j] == (Object)(object)val) { num = j; break; } } if (num < 0) { Log.LogWarning((object)"Remote teleporter blocked: local player was not found."); ShowNotification("WarpBack", "Unable to select the local player."); return; } Log.LogInfo((object)("WarpBack: Switching radar target to local player. " + $"Index: {num}, " + $"Player ID: {val.playerClientId}")); StartOfRound.Instance.mapScreen.SwitchRadarTargetAndSync(num); Log.LogInfo((object)("WarpBack: Activating normal teleporter. " + $"Player ID: {val.playerClientId}, " + $"Teleporter ID: {val2.teleporterId}")); val2.PressTeleportButtonOnLocalClient(); Log.LogInfo((object)("WarpBack: PressTeleportButtonOnLocalClient() called. " + $"Player ID: {val.playerClientId}, " + $"Teleporter ID: {val2.teleporterId}")); ShowNotification("WarpBack", "Teleporter request sent."); } } public static void TryWarpLocalPlayer() { //IL_0227: Unknown result type (might be due to invalid IL or missing references) //IL_022c: Unknown result type (might be due to invalid IL or missing references) //IL_022e: Unknown result type (might be due to invalid IL or missing references) //IL_027e: Unknown result type (might be due to invalid IL or missing references) //IL_02a3: Unknown result type (might be due to invalid IL or missing references) //IL_02b8: Unknown result type (might be due to invalid IL or missing references) //IL_02cd: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)StartOfRound.Instance == (Object)null) { Log.LogWarning((object)"Initial position warp blocked: StartOfRound instance not found."); ShowNotification("WarpBack", "Unable to access the current game state."); return; } PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if ((Object)(object)val == (Object)null) { Log.LogWarning((object)"Initial position warp blocked: local player not found."); ShowNotification("WarpBack", "Unable to find the local player."); return; } if (!StartOfRound.Instance.inShipPhase) { Log.LogInfo((object)"Initial position warp blocked: not in orbit."); ShowNotification("WarpBack", "This function can only be used while in orbit."); return; } if (val.inTerminalMenu) { Log.LogInfo((object)"Initial position warp blocked: terminal menu open."); ShowNotification("WarpBack", "Please close the terminal before using this function."); return; } if (val.isTypingChat) { Log.LogInfo((object)"Initial position warp blocked: player is typing chat."); ShowNotification("WarpBack", "This function cannot be used while typing in chat."); return; } Terminal val2 = Object.FindObjectOfType(); if ((Object)(object)val2 != (Object)null && val2.terminalInUse) { Log.LogInfo((object)"Initial position warp blocked: terminal is in use."); ShowNotification("WarpBack", "This function cannot be used while the terminal is in use."); return; } if ((Object)(object)HUDManager.Instance != (Object)null && (Object)(object)HUDManager.Instance.chatTextField != (Object)null && HUDManager.Instance.chatTextField.isFocused) { Log.LogInfo((object)"Initial position warp blocked: chat field focused."); ShowNotification("WarpBack", "This function cannot be used while typing in chat."); return; } if (val.isPlayerDead) { Log.LogInfo((object)"Initial position warp blocked: player is dead."); ShowNotification("WarpBack", "You cannot warp while dead."); return; } Transform shipSpawnPoint = GetShipSpawnPoint(); if ((Object)(object)shipSpawnPoint == (Object)null) { Log.LogWarning((object)"Initial position warp blocked: failed to find ship spawn point."); ShowNotification("WarpBack", "The initial ship position could not be found."); return; } Vector3 position = shipSpawnPoint.position; val.TeleportPlayer(position, false, 0f, false, true); val.isInElevator = true; val.isInHangarShipRoom = true; val.isInsideFactory = false; val.ResetPlayerBloodObjects(true); Log.LogInfo((object)("InitialPositionWarp: Warped player " + $"{val.playerClientId} " + $"to initial ship position {position}")); ShowNotification("WarpBack", "Warped to the initial ship position.\n" + $"X: {position.x:F1} " + $"Y: {position.y:F1} " + $"Z: {position.z:F1}"); } private static bool CanUseWarpFunctions(PlayerControllerB localPlayer) { if (!StartOfRound.Instance.inShipPhase) { Log.LogInfo((object)"WarpBack function blocked: not in orbit."); ShowNotification("WarpBack", "This function can only be used while in orbit."); return false; } if (localPlayer.inTerminalMenu) { Log.LogInfo((object)"Warp function blocked: terminal menu open."); ShowNotification("WarpBack", "Please close the terminal before using this function."); return false; } if (localPlayer.isTypingChat) { Log.LogInfo((object)"Warp function blocked: player is typing chat."); ShowNotification("WarpBack", "This function cannot be used while typing in chat."); return false; } Terminal val = Object.FindObjectOfType(); if ((Object)(object)val != (Object)null && val.terminalInUse) { Log.LogInfo((object)"Warp function blocked: terminal is in use."); ShowNotification("WarpBack", "This function cannot be used while the terminal is in use."); return false; } if ((Object)(object)HUDManager.Instance != (Object)null && (Object)(object)HUDManager.Instance.chatTextField != (Object)null && HUDManager.Instance.chatTextField.isFocused) { Log.LogInfo((object)"Warp function blocked: chat field focused."); return false; } return true; } private static void ShowNotification(string title, string message) { Log.LogInfo((object)("Notification: " + title + " - " + message)); if ((Object)(object)HUDManager.Instance == (Object)null) { return; } try { HUDManager.Instance.DisplayTip(title, message, false, false, "LC_Tip1"); } catch (Exception arg) { Log.LogWarning((object)$"Failed to display notification: {arg}"); } } private static Transform GetShipSpawnPoint() { if ((Object)(object)StartOfRound.Instance == (Object)null) { return null; } if (StartOfRound.Instance.playerSpawnPositions == null) { return null; } if (StartOfRound.Instance.playerSpawnPositions.Length == 0) { return null; } return StartOfRound.Instance.playerSpawnPositions[0]; } } [HarmonyPatch(typeof(HUDManager))] internal static class HUDManagerPatch { [HarmonyPatch("Update")] [HarmonyPostfix] private static void UpdatePatch() { WarpBackPlugin.CheckInput(); } }