Please disclose if any significant portion of your mod was created 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 AzureWarp v0.3.3
BepInEx\plugins\AzureWarp\AzureWarp.dll
Decompiled 3 weeks agousing System; using System.Collections; using System.Collections.Generic; 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 LethalCompanyInputUtils.Api; using LethalConfig; using LethalConfig.ConfigItems; using Microsoft.CodeAnalysis; using StaticNetcodeLib; using Unity.Netcode; using UnityEngine; using UnityEngine.InputSystem; [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("AzureWarp")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.3.3.0")] [assembly: AssemblyInformationalVersion("0.3.3+1ce40c627c84f8118b3e12ba46ffefe71cb34176")] [assembly: AssemblyProduct("AzureWarp")] [assembly: AssemblyTitle("AzureWarp")] [assembly: AssemblyVersion("0.3.3.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [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; } } [CompilerGenerated] [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; } } [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 AzureWarp { [HarmonyPatch] internal static class InversePatches { private static bool _suppressDrop; private static bool _connectHooked; [HarmonyPatch(typeof(ShipTeleporter), "TeleportPlayerOutWithInverseTeleporter")] [HarmonyPrefix] private static void InverseWarp_Prefix() { _suppressDrop = WarpManager.EffectiveInverseKeepItems(); } [HarmonyPatch(typeof(ShipTeleporter), "TeleportPlayerOutWithInverseTeleporter")] [HarmonyFinalizer] private static void InverseWarp_Finalizer() { _suppressDrop = false; } [HarmonyPatch(typeof(PlayerControllerB), "DropAllHeldItems")] [HarmonyPrefix] private static bool DropAllHeldItems_Prefix() { if (_suppressDrop) { Plugin.Log.LogInfo((object)"[InverseWarp] Kept held items through the inverse teleporter (drop suppressed)."); return false; } return true; } [HarmonyPatch(typeof(ShipTeleporter), "Awake")] [HarmonyPostfix] private static void ShipTeleporter_Awake_Postfix(ShipTeleporter __instance) { if ((Object)(object)__instance != (Object)null && __instance.isInverseTeleporter) { ApplyInverseCooldown(__instance); } } internal static void ApplyInverseCooldown(ShipTeleporter tp) { if ((Object)(object)tp == (Object)null || !tp.isInverseTeleporter) { return; } var (flag, num) = WarpManager.EffectiveInverseCooldown(); if (flag) { tp.cooldownAmount = num; Traverse val = Traverse.Create((object)tp).Field("cooldownTime"); if (val.FieldExists() && val.GetValue<float>() > num) { val.SetValue((object)num); } Plugin.Log.LogInfo((object)$"[InverseWarp] Inverse teleporter cooldown set to {num}s."); } } internal static void ApplyInverseCooldownToActive() { ShipTeleporter[] array = Object.FindObjectsOfType<ShipTeleporter>(); for (int i = 0; i < array.Length; i++) { ApplyInverseCooldown(array[i]); } } [HarmonyPatch(typeof(StartOfRound), "Start")] [HarmonyPostfix] private static void StartOfRound_Start_Postfix() { NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null || !singleton.IsServer) { return; } WarpManager.BroadcastInverseKeepItems(); WarpManager.BroadcastInverseCooldown(); if (!_connectHooked) { _connectHooked = true; singleton.OnClientConnectedCallback += delegate { WarpManager.BroadcastInverseKeepItems(); WarpManager.BroadcastInverseCooldown(); }; } } } [BepInPlugin("com.azurecore.azurewarp", "AzureWarp", "0.3.3")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { public const string Guid = "com.azurecore.azurewarp"; public const string Version = "0.3.3"; internal static ManualLogSource Log; internal static WarpConfig Cfg; internal static WarpKeybinds Keybinds; internal static Plugin Instance; private void Awake() { //IL_004b: Unknown result type (might be due to invalid IL or missing references) Instance = this; Log = ((BaseUnityPlugin)this).Logger; Cfg = new WarpConfig(((BaseUnityPlugin)this).Config); Keybinds = new WarpKeybinds(); Keybinds.WarpToShip.performed += OnWarpPressed; new Harmony("com.azurecore.azurewarp").PatchAll(); Log.LogInfo((object)"AzureWarp 0.3.3 loaded — Chaos Gate online. Press to warp home."); } private void OnWarpPressed(CallbackContext ctx) { if (((CallbackContext)(ref ctx)).performed) { WarpManager.TryLocalWarp(); } } } public class WarpConfig { public readonly ConfigEntry<bool> KeepHeldItems; public readonly ConfigEntry<bool> PlayBuildupAnimation; public readonly ConfigEntry<bool> UseVanillaCooldown; public readonly ConfigEntry<float> CustomCooldownSeconds; public readonly ConfigEntry<bool> KeepItemsOnInverseWarp; public readonly ConfigEntry<bool> OverrideInverseCooldown; public readonly ConfigEntry<float> InverseCooldownSeconds; public WarpConfig(ConfigFile cfg) { //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Expected O, but got Unknown //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Expected O, but got Unknown //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Expected O, but got Unknown //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Expected O, but got Unknown //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Expected O, but got Unknown //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Expected O, but got Unknown //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Expected O, but got Unknown KeepHeldItems = cfg.Bind<bool>("General", "KeepHeldItems", true, "Keep your held items when you warp to the ship. Server-authoritative: your items move with you rather than being dropped, so nothing duplicates."); PlayBuildupAnimation = cfg.Bind<bool>("General", "PlayBuildupAnimation", true, "Play the ship teleporter's ~3 second beam-up buildup before warping (spin-up sound + beam animation), just like the vanilla teleporter. You are NOT protected during the charge — like a .hack return scroll, you can be caught mid-warp. Turn OFF for an instant beam flash."); UseVanillaCooldown = cfg.Bind<bool>("Cooldown", "UseVanillaCooldown", true, "Use the ship teleporter's standard 10s cooldown for warps."); CustomCooldownSeconds = cfg.Bind<float>("Cooldown", "CustomCooldownSeconds", 10f, "Cooldown (seconds) used only when UseVanillaCooldown is false."); KeepItemsOnInverseWarp = cfg.Bind<bool>("Inverse Teleporter", "KeepItemsOnInverseWarp", true, "When you use the ship's INVERSE teleporter (the one that sends you INTO the facility), keep your held items instead of dropping them on the ship floor. HOST-AUTHORITATIVE: the host's value is auto-synced to everyone in the lobby, so items never duplicate. Does not touch the regular teleporter."); OverrideInverseCooldown = cfg.Bind<bool>("Inverse Teleporter", "OverrideInverseCooldown", false, "Override the ship's INVERSE teleporter cooldown. Vanilla is 210 seconds. Turn this ON to use InverseCooldownSeconds instead. HOST-AUTHORITATIVE (the host's value applies to the whole lobby)."); InverseCooldownSeconds = cfg.Bind<float>("Inverse Teleporter", "InverseCooldownSeconds", 10f, "Inverse teleporter cooldown in seconds, used only when OverrideInverseCooldown is ON. Set to 10 to match the regular teleporter. (Vanilla default is 210.)"); LethalConfigManager.AddConfigItem((BaseConfigItem)new BoolCheckBoxConfigItem(KeepHeldItems, false)); LethalConfigManager.AddConfigItem((BaseConfigItem)new BoolCheckBoxConfigItem(PlayBuildupAnimation, false)); LethalConfigManager.AddConfigItem((BaseConfigItem)new BoolCheckBoxConfigItem(UseVanillaCooldown, false)); LethalConfigManager.AddConfigItem((BaseConfigItem)new FloatInputFieldConfigItem(CustomCooldownSeconds, false)); LethalConfigManager.AddConfigItem((BaseConfigItem)new BoolCheckBoxConfigItem(KeepItemsOnInverseWarp, false)); LethalConfigManager.AddConfigItem((BaseConfigItem)new BoolCheckBoxConfigItem(OverrideInverseCooldown, false)); LethalConfigManager.AddConfigItem((BaseConfigItem)new FloatInputFieldConfigItem(InverseCooldownSeconds, false)); } } public class WarpKeybinds : LcInputActions { [InputAction(/*Could not decode attribute arguments.*/)] public InputAction WarpToShip { get; set; } } [StaticNetcode] public static class WarpManager { private const float BuildupSeconds = 3f; private static float _cooldownUntil; private static bool? _syncedInverseKeepItems; private static bool? _syncedOverrideInverseCooldown; private static float? _syncedInverseCooldownSeconds; public static bool EffectiveInverseKeepItems() { NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton != (Object)null && singleton.IsServer) { return Plugin.Cfg.KeepItemsOnInverseWarp.Value; } return _syncedInverseKeepItems ?? Plugin.Cfg.KeepItemsOnInverseWarp.Value; } public static void BroadcastInverseKeepItems() { NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null || !singleton.IsServer) { return; } try { SyncInverseKeepItemsClientRpc(Plugin.Cfg.KeepItemsOnInverseWarp.Value); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[InverseWarp] Setting broadcast deferred (network not ready yet): " + ex.Message)); } } [ClientRpc] public static void SyncInverseKeepItemsClientRpc(bool keepItems) { _syncedInverseKeepItems = keepItems; Plugin.Log.LogInfo((object)$"[InverseWarp] Host setting synced: KeepItemsOnInverseWarp={keepItems}."); } public static (bool over, float seconds) EffectiveInverseCooldown() { NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton != (Object)null && singleton.IsServer) { return (over: Plugin.Cfg.OverrideInverseCooldown.Value, seconds: Plugin.Cfg.InverseCooldownSeconds.Value); } return (over: _syncedOverrideInverseCooldown ?? Plugin.Cfg.OverrideInverseCooldown.Value, seconds: _syncedInverseCooldownSeconds ?? Plugin.Cfg.InverseCooldownSeconds.Value); } public static void BroadcastInverseCooldown() { NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null || !singleton.IsServer) { return; } try { SyncInverseCooldownClientRpc(Plugin.Cfg.OverrideInverseCooldown.Value, Plugin.Cfg.InverseCooldownSeconds.Value); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[InverseWarp] Cooldown broadcast deferred (network not ready yet): " + ex.Message)); } } [ClientRpc] public static void SyncInverseCooldownClientRpc(bool over, float seconds) { _syncedOverrideInverseCooldown = over; _syncedInverseCooldownSeconds = seconds; Plugin.Log.LogInfo((object)$"[InverseWarp] Host cooldown synced: override={over}, seconds={seconds}."); InversePatches.ApplyInverseCooldownToActive(); } public static void TryLocalWarp() { PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if (!((Object)(object)val == (Object)null) && val.isPlayerControlled && !val.isPlayerDead && !((Object)(object)StartOfRound.Instance == (Object)null) && !StartOfRound.Instance.shipIsLeaving) { RequestWarpServerRpc(val.actualClientId); } } [ServerRpc(RequireOwnership = false)] public static void RequestWarpServerRpc(ulong clientId) { //IL_00d1: 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) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) ShipTeleporter val = FindRegularTeleporter(); if ((Object)(object)val == (Object)null) { DenyWarpClientRpc(clientId, "No teleporter on the ship."); return; } float realtimeSinceStartup = Time.realtimeSinceStartup; if (realtimeSinceStartup < _cooldownUntil) { int num = Mathf.CeilToInt(_cooldownUntil - realtimeSinceStartup); DenyWarpClientRpc(clientId, $"Chaos Gate on cooldown ({num}s)."); return; } PlayerControllerB val2 = FindPlayer(clientId); if ((Object)(object)val2 == (Object)null) { return; } if (val2.isInHangarShipRoom) { DenyWarpClientRpc(clientId, "You're already on the ship."); return; } float num2 = (Plugin.Cfg.UseVanillaCooldown.Value ? 10f : Mathf.Max(0f, Plugin.Cfg.CustomCooldownSeconds.Value)); _cooldownUntil = realtimeSinceStartup + num2; bool value = Plugin.Cfg.KeepHeldItems.Value; bool value2 = Plugin.Cfg.PlayBuildupAnimation.Value; Vector3 val3 = TeleporterPad(val); Plugin.Log.LogInfo((object)$"[Host] Warp granted to clientId {clientId} (keepItems={value}, buildup={value2}, dest={val3}, cooldown={num2}s)."); if (value2) { BeginWarpClientRpc(clientId); } else { ExecuteWarpClientRpc(clientId, value, val3); } } [ClientRpc] public static void BeginWarpClientRpc(ulong clientId) { PlayerControllerB val = FindPlayer(clientId); if ((Object)(object)val == (Object)null) { return; } ShipTeleporter val2 = FindRegularTeleporter(); if ((Object)(object)val2 != (Object)null) { if ((Object)(object)val2.shipTeleporterAudio != (Object)null && (Object)(object)val2.teleporterSpinSFX != (Object)null) { val2.shipTeleporterAudio.PlayOneShot(val2.teleporterSpinSFX); } if ((Object)(object)val.movementAudio != (Object)null && (Object)(object)val2.teleporterSpinSFX != (Object)null) { val.movementAudio.PlayOneShot(val2.teleporterSpinSFX); } } if ((Object)(object)val.beamUpParticle != (Object)null) { val.beamUpParticle.Play(); ((MonoBehaviour)Plugin.Instance).StartCoroutine(StopBuildupParticleAfter(val)); Plugin.Log.LogInfo((object)$"[Warp] Buildup VFX started for clientId {clientId}."); } if ((Object)(object)val == (Object)(object)GameNetworkManager.Instance?.localPlayerController) { ((MonoBehaviour)(((Object)(object)val2 != (Object)null) ? ((Plugin)(object)val2) : Plugin.Instance)).StartCoroutine(OwnerChargeThenComplete(val, clientId)); } } private static IEnumerator StopBuildupParticleAfter(PlayerControllerB player) { yield return (object)new WaitForSeconds(3.25f); if ((Object)(object)player != (Object)null && (Object)(object)player.beamUpParticle != (Object)null) { player.beamUpParticle.Stop(true, (ParticleSystemStopBehavior)0); } } private static IEnumerator OwnerChargeThenComplete(PlayerControllerB player, ulong clientId) { yield return (object)new WaitForSeconds(3f); if ((Object)(object)player == (Object)null || player.isPlayerDead || ((Object)(object)StartOfRound.Instance != (Object)null && StartOfRound.Instance.shipIsLeaving)) { Plugin.Log.LogInfo((object)$"[Warp] Charge fizzled for clientId {clientId} (died/left/ship leaving during charge)."); } else { CompleteWarpServerRpc(clientId); } } [ServerRpc(RequireOwnership = false)] public static void CompleteWarpServerRpc(ulong clientId) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) ShipTeleporter val = FindRegularTeleporter(); if (!((Object)(object)val == (Object)null)) { PlayerControllerB val2 = FindPlayer(clientId); if (!((Object)(object)val2 == (Object)null) && !val2.isInHangarShipRoom) { ExecuteWarpClientRpc(clientId, Plugin.Cfg.KeepHeldItems.Value, TeleporterPad(val)); } } } [ClientRpc] public static void ExecuteWarpClientRpc(ulong clientId, bool keepItems, Vector3 destination) { //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) PlayerControllerB val = FindPlayer(clientId); if ((Object)(object)val == (Object)null) { return; } bool flag = (Object)(object)val == (Object)(object)GameNetworkManager.Instance?.localPlayerController; ShipTeleporter val2 = FindRegularTeleporter(); if ((Object)(object)val2 != (Object)null && (Object)(object)val2.shipTeleporterAudio != (Object)null && (Object)(object)val2.teleporterBeamUpSFX != (Object)null) { val2.shipTeleporterAudio.PlayOneShot(val2.teleporterBeamUpSFX); } if ((Object)(object)val.beamUpParticle != (Object)null) { val.beamUpParticle.Stop(true, (ParticleSystemStopBehavior)0); val.beamUpParticle.Play(); } if ((Object)(object)val2 != (Object)null && (Object)(object)val.movementAudio != (Object)null && (Object)(object)val2.beamUpPlayerBodySFX != (Object)null) { val.movementAudio.PlayOneShot(val2.beamUpPlayerBodySFX); } if (flag) { HUDManager instance = HUDManager.Instance; if (instance != null) { instance.ShakeCamera((ScreenShakeType)1); } } if (!keepItems && flag) { val.DropAllHeldItems(true, false, false, false, default(Vector3), default(Vector3), default(Vector3), default(Vector3), default(Vector3)); } val.TeleportPlayer(destination, false, 0f, false, true); val.isInElevator = true; val.isInHangarShipRoom = true; val.isInsideFactory = false; TimeOfDay obj = Object.FindObjectOfType<TimeOfDay>(); if (obj != null) { obj.SetInsideLightingDimness(false, false); } Plugin.Log.LogInfo((object)$"[Warp] Executed warp for clientId {clientId} to {destination} (keepItems={keepItems}, localOwner={flag}, insideFactory={val.isInsideFactory})."); if (flag) { HUDManager instance2 = HUDManager.Instance; if (instance2 != null) { instance2.DisplayTip("Chaos Gate", keepItems ? "Warped to the ship." : "Warped to the ship. Items left behind.", false, false, "LC_Tip1"); } } } [ClientRpc] public static void DenyWarpClientRpc(ulong clientId, string reason) { PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if (!((Object)(object)val == (Object)null) && val.actualClientId == clientId) { HUDManager instance = HUDManager.Instance; if (instance != null) { instance.DisplayTip("Chaos Gate", reason, false, false, "LC_Tip1"); } } } private static Vector3 TeleporterPad(ShipTeleporter tp) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)tp.teleporterPosition != (Object)null)) { return ((Component)tp).transform.position; } return tp.teleporterPosition.position; } private static ShipTeleporter? FindRegularTeleporter() { return ((IEnumerable<ShipTeleporter>)Object.FindObjectsOfType<ShipTeleporter>()).FirstOrDefault((Func<ShipTeleporter, bool>)((ShipTeleporter t) => !t.isInverseTeleporter)); } private static PlayerControllerB? FindPlayer(ulong clientId) { return StartOfRound.Instance?.allPlayerScripts?.FirstOrDefault((Func<PlayerControllerB, bool>)((PlayerControllerB p) => (Object)(object)p != (Object)null && p.actualClientId == clientId)); } } }