// Consolidated decompiled source — Azumatt-Unstuck v1.0.0 // Generated by Hexium's decompiled-source browser. Best-effort concatenation of every type in this // version's manifest — decompiler output isn't guaranteed to compile as-is. using System; using System.Runtime.CompilerServices; using Microsoft.CodeAnalysis; using System.IO; using System.Reflection; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using JetBrains.Annotations; using UnityEngine; using System.Linq; // ---- Unstuck.dll :: Microsoft.CodeAnalysis.EmbeddedAttribute ---- namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } // ---- Unstuck.dll :: System.Runtime.CompilerServices.NullableAttribute ---- namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } } // ---- Unstuck.dll :: System.Runtime.CompilerServices.NullableContextAttribute ---- namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } } // ---- Unstuck.dll :: Unstuck.UnstuckPlugin ---- namespace Unstuck { [BepInPlugin("Azumatt.Unstuck", "Unstuck", "1.0.0")] public class UnstuckPlugin : BaseUnityPlugin { public enum Toggle { On = 1, Off = 0 } private class ConfigurationManagerAttributes { [UsedImplicitly] public int? Order; [UsedImplicitly] public bool? Browsable; [UsedImplicitly] public string? Category; [UsedImplicitly] public Action? CustomDrawer; } private class AcceptableShortcuts : AcceptableValueBase { public AcceptableShortcuts() : base(typeof(KeyboardShortcut)) { } public override object Clamp(object value) { return value; } public override bool IsValid(object value) { return true; } public override string ToDescriptionString() { return "# Acceptable values: " + string.Join(", ", UnityInput.Current.SupportedKeyCodes); } } internal const string ModName = "Unstuck"; internal const string ModVersion = "1.0.0"; internal const string Author = "Azumatt"; private const string ModGUID = "Azumatt.Unstuck"; private static string ConfigFileName = "Azumatt.Unstuck.cfg"; private static string ConfigFileFullPath; private readonly Harmony _harmony = new Harmony("Azumatt.Unstuck"); public static readonly ManualLogSource UnstuckLogger; internal static ConfigEntry hotkey; internal static ConfigEntry searchRadius; internal static ConfigEntry maxSearchRadius; internal static ConfigEntry searchIncrement; internal static ConfigEntry onlyUnderwater; public static Global gInst => Global.code; public static FPSPlayer fpspInst => FPSPlayer.code; public static Camera camInst => gInst.player.mainCamera; public void Awake() { hotkey = base.Config.Bind("1 - General", "Hotkey", new KeyboardShortcut(KeyCode.G), "Keyboard shortcut to trigger unstuck."); searchRadius = base.Config.Bind("1 - General", "Search Radius", 10f, "Starting search radius."); maxSearchRadius = base.Config.Bind("1 - General", "Maximum Search Radius", 30f, "Maximum radius to search"); searchIncrement = base.Config.Bind("1 - General", "Increment Step", 0.5f, "Increment step when expanding search"); onlyUnderwater = base.Config.Bind("1 - General", "Only Underwater", defaultValue: true, "Allow unstuck only when underwater. Pressing the key on land will not do anything if on."); Assembly executingAssembly = Assembly.GetExecutingAssembly(); _harmony.PatchAll(executingAssembly); SetupWatcher(); } private void Update() { if (Input.anyKey && !((UnityEngine.Object)(object)FPSRigidBodyWalker.code == null) && (UnityEngine.Object)(object)fpspInst != null && hotkey.Value.IsKeyDown() && (!onlyUnderwater.Value || FPSRigidBodyWalker.code.isUnderWater)) { MoveToSafePosition(((Component)(object)fpspInst).transform); } } private void MoveToSafePosition(Transform playerTransform) { if (IsPositionOverlapping(playerTransform.position)) { Vector3 vector = FindSafePosition(playerTransform); if (vector != Vector3.zero) { playerTransform.position = vector; } else { UnstuckLogger.LogWarning("No safe position found within the maximum search radius."); } } } private bool IsPositionOverlapping(Vector3 position) { int num = LayerMask.NameToLayer("Player Bone"); int layerMask = ~(1 << num); Collider[] array = Physics.OverlapSphere(position, searchRadius.Value, layerMask); bool result = false; Collider[] array2 = array; foreach (Collider collider in array2) { if (!(collider.gameObject.name == "Ocean") && !(collider.gameObject.name == "Water Build Collider") && !(collider.gameObject.name == "WorldCreatorTerrain") && !(collider.gameObject.name == "EnviroSky Standard") && !collider.transform.root.name.ToLower().Contains("player")) { result = true; } } return result; } private Vector3 FindSafePosition(Transform playerTransform) { for (float num = searchRadius.Value; num <= maxSearchRadius.Value; num += searchIncrement.Value) { Vector3[] array = new Vector3[6] { Vector3.forward, Vector3.back, Vector3.right, Vector3.left, Vector3.up, Vector3.down }; foreach (Vector3 vector in array) { Vector3 vector2 = playerTransform.position + vector * num; if (!IsPositionOverlapping(vector2)) { return vector2; } } } return Vector3.zero; } private void OnDestroy() { base.Config.Save(); } private void SetupWatcher() { FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(Paths.ConfigPath, ConfigFileName); fileSystemWatcher.Changed += ReadConfigValues; fileSystemWatcher.Created += ReadConfigValues; fileSystemWatcher.Renamed += ReadConfigValues; fileSystemWatcher.IncludeSubdirectories = true; fileSystemWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject; fileSystemWatcher.EnableRaisingEvents = true; } private void ReadConfigValues(object sender, FileSystemEventArgs e) { if (!File.Exists(ConfigFileFullPath)) { return; } try { UnstuckLogger.LogDebug("ReadConfigValues called"); base.Config.Reload(); } catch { UnstuckLogger.LogError("There was an issue loading your " + ConfigFileName); UnstuckLogger.LogError("Please check your config entries for spelling and format!"); } } internal ConfigEntry TextEntryConfig(string group, string name, T value, string desc) { ConfigurationManagerAttributes configurationManagerAttributes = new ConfigurationManagerAttributes { CustomDrawer = TextAreaDrawer }; return base.Config.Bind(group, name, value, new ConfigDescription(desc, null, configurationManagerAttributes)); } internal static void TextAreaDrawer(ConfigEntryBase entry) { GUILayout.ExpandHeight(expand: true); GUILayout.ExpandWidth(expand: true); entry.BoxedValue = GUILayout.TextArea((string)entry.BoxedValue, GUILayout.ExpandWidth(expand: true), GUILayout.ExpandHeight(expand: true)); } static UnstuckPlugin() { string configPath = Paths.ConfigPath; char directorySeparatorChar = Path.DirectorySeparatorChar; ConfigFileFullPath = configPath + directorySeparatorChar + ConfigFileName; UnstuckLogger = BepInEx.Logging.Logger.CreateLogSource("Unstuck"); hotkey = null; searchRadius = null; maxSearchRadius = null; searchIncrement = null; onlyUnderwater = null; } } } // ---- Unstuck.dll :: Unstuck.KeyboardExtensions ---- namespace Unstuck { public static class KeyboardExtensions { public static bool IsKeyDown(this KeyboardShortcut shortcut) { if (shortcut.MainKey != KeyCode.None && Input.GetKeyDown(shortcut.MainKey)) { return shortcut.Modifiers.All(Input.GetKey); } return false; } public static bool IsKeyHeld(this KeyboardShortcut shortcut) { if (shortcut.MainKey != KeyCode.None && Input.GetKey(shortcut.MainKey)) { return shortcut.Modifiers.All(Input.GetKey); } return false; } } }