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 Dio Company v1.0.1
BepInEx/plugins/Dio_Company/Dio_Company.dll
Decompiled 9 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using DioCompany.Networking; using GameNetcodeStuff; using HarmonyLib; using LethalNetworkAPI; using Microsoft.CodeAnalysis; using Unity.Netcode; using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; using UnityEngine.Networking; using UnityEngine.Rendering; using UnityEngine.Rendering.HighDefinition; using UnityEngine.VFX; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyVersion("0.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 DioCompany { public static class DamageQueue { private class Entry { public EnemyAI Enemy; public int Force; public Vector3 HitDirection; public PlayerControllerB PlayerWhoHit; public bool PlayHitSFX; public int HitId; } private static readonly List<Entry> Pending = new List<Entry>(); public static void Enqueue(EnemyAI enemy, int force, Vector3 hitDirection, PlayerControllerB playerWhoHit, bool playHitSFX, int hitId) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) Pending.Add(new Entry { Enemy = enemy, Force = force, HitDirection = hitDirection, PlayerWhoHit = playerWhoHit, PlayHitSFX = playHitSFX, HitId = hitId }); } public static void ReplayAndClear() { //IL_004c: Unknown result type (might be due to invalid IL or missing references) if (Pending.Count == 0) { return; } List<Entry> list = new List<Entry>(Pending); Pending.Clear(); foreach (Entry item in list) { if (!((Object)(object)item.Enemy == (Object)null)) { item.Enemy.HitEnemyOnLocalClient(item.Force, item.HitDirection, item.PlayerWhoHit, item.PlayHitSFX, item.HitId); } } } } public static class ElevatorFreeze { public static void Freeze() { SetFrozen(frozen: true); } public static void Unfreeze() { SetFrozen(frozen: false); } private static void SetFrozen(bool frozen) { MineshaftElevatorController val = RoundManager.Instance?.currentMineshaftElevator; if (!((Object)(object)val == (Object)null)) { if ((Object)(object)val.elevatorAnimator != (Object)null) { val.elevatorAnimator.speed = (frozen ? 0f : 1f); } AudioSource[] componentsInChildren = ((Component)val).GetComponentsInChildren<AudioSource>(true); for (int i = 0; i < componentsInChildren.Length; i++) { componentsInChildren[i].mute = frozen; } } } } public static class EnemyFreeze { public static void Freeze() { SetFrozen(frozen: true); } public static void Unfreeze() { SetFrozen(frozen: false); } private static void SetFrozen(bool frozen) { List<EnemyAI> list = RoundManager.Instance?.SpawnedEnemies; if (list == null) { return; } foreach (EnemyAI item in list) { if ((Object)(object)item == (Object)null) { continue; } if ((Object)(object)item.agent != (Object)null) { item.agent.isStopped = frozen; } if ((Object)(object)item.creatureAnimator != (Object)null) { item.creatureAnimator.speed = (frozen ? 0f : 1f); } AudioSource[] componentsInChildren = ((Component)item).GetComponentsInChildren<AudioSource>(true); for (int i = 0; i < componentsInChildren.Length; i++) { componentsInChildren[i].mute = frozen; } VisualEffect[] componentsInChildren2 = ((Component)item).GetComponentsInChildren<VisualEffect>(true); for (int i = 0; i < componentsInChildren2.Length; i++) { componentsInChildren2[i].pause = frozen; } ParticleSystem[] componentsInChildren3 = ((Component)item).GetComponentsInChildren<ParticleSystem>(true); foreach (ParticleSystem val in componentsInChildren3) { if (frozen) { val.Pause(true); } else { val.Play(true); } } } } } public static class HostPermissions { public static readonly HashSet<ulong> AllowedClientIds = new HashSet<ulong>(); public static bool IsAllowed(ulong clientId) { if ((Object)(object)NetworkManager.Singleton != (Object)null && clientId == 0L) { return true; } return AllowedClientIds.Contains(clientId); } } public static class MineFreeze { public static readonly List<Landmine> Active = new List<Landmine>(); public static void Freeze() { SetFrozen(frozen: true); } public static void Unfreeze() { SetFrozen(frozen: false); } private static void SetFrozen(bool frozen) { foreach (Landmine item in Active) { if (!((Object)(object)item == (Object)null)) { if ((Object)(object)item.mineAnimator != (Object)null) { item.mineAnimator.speed = (frozen ? 0f : 1f); } AudioSource[] componentsInChildren = ((Component)item).GetComponentsInChildren<AudioSource>(true); for (int i = 0; i < componentsInChildren.Length; i++) { componentsInChildren[i].mute = frozen; } } } } } public static class MineQueue { private static readonly MethodInfo TriggerMethod = AccessTools.Method(typeof(Landmine), "TriggerMineOnLocalClientByExiting", (Type[])null, (Type[])null); private static readonly List<Landmine> Pending = new List<Landmine>(); public static void Enqueue(Landmine mine) { Pending.Add(mine); } public static void ReplayAndClear() { if (Pending.Count == 0) { return; } List<Landmine> list = new List<Landmine>(Pending); Pending.Clear(); foreach (Landmine item in list) { if (!((Object)(object)item == (Object)null)) { TriggerMethod?.Invoke(item, null); } } } } public static class ModTick { public static void Tick() { //IL_000f: Unknown result type (might be due to invalid IL or missing references) Keyboard current = Keyboard.current; if (current != null && ((ButtonControl)current[Plugin.PauseKey.Value]).wasPressedThisFrame) { PauseController.LocalKeyPressed(); } if (PauseState.IsPaused && (Object)(object)NetworkManager.Singleton != (Object)null && NetworkManager.Singleton.IsHost && Time.realtimeSinceStartup >= PauseState.PauseEndsAtRealtime) { PauseController.ResumeFromHost(); } PauseEffects.Tick(); PauseAudio.Tick(); ScanPulse.Tick(); } } public static class PauseAudio { private class PendingLoad { public UnityWebRequest Request; public UnityWebRequestAsyncOperation Operation; public Action<AudioClip> OnLoaded; } private static readonly List<PendingLoad> Pending = new List<PendingLoad>(); private static AudioClip _pauseClip; private static AudioClip _resumeClip; private static bool _loadStarted; public static void LoadClips() { if (!_loadStarted) { _loadStarted = true; StartLoad("DioCompany.Resources.pause_sfx.mp3", delegate(AudioClip clip) { _pauseClip = clip; }); StartLoad("DioCompany.Resources.resume_sfx.mp3", delegate(AudioClip clip) { _resumeClip = clip; }); } } public static void Tick() { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Invalid comparison between Unknown and I4 if (Pending.Count == 0) { return; } for (int num = Pending.Count - 1; num >= 0; num--) { PendingLoad pendingLoad = Pending[num]; if (((AsyncOperation)pendingLoad.Operation).isDone) { if ((int)pendingLoad.Request.result == 1) { pendingLoad.OnLoaded(DownloadHandlerAudioClip.GetContent(pendingLoad.Request)); } pendingLoad.Request.Dispose(); Pending.RemoveAt(num); } } } public static void PlayPause() { PlayOneShot(_pauseClip); } public static void PlayResume() { PlayOneShot(_resumeClip); } private static void PlayOneShot(AudioClip clip) { if (!((Object)(object)clip == (Object)null)) { AudioSource val = (((Object)(object)HUDManager.Instance != (Object)null) ? HUDManager.Instance.UIAudio : null); if ((Object)(object)val != (Object)null) { val.PlayOneShot(clip); } } } private static void StartLoad(string resourceName, Action<AudioClip> onLoaded) { using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName); if (stream != null) { string text = Path.Combine(Path.GetTempPath(), Path.GetFileName(resourceName)); using (FileStream destination = File.Create(text)) { stream.CopyTo(destination); } UnityWebRequest audioClip = UnityWebRequestMultimedia.GetAudioClip("file://" + text, (AudioType)13); UnityWebRequestAsyncOperation operation = audioClip.SendWebRequest(); Pending.Add(new PendingLoad { Request = audioClip, Operation = operation, OnLoaded = onLoaded }); } } } public static class PauseController { public static void LocalKeyPressed() { PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if ((Object)(object)val == (Object)null) { return; } if (PauseState.IsPaused) { if (PauseState.CasterClientId == val.playerClientId) { PauseNetworking.RequestToggle(); } } else { PauseNetworking.RequestToggle(); } } public static void HostHandleToggleRequest(ulong senderClientId) { //IL_0101: Unknown result type (might be due to invalid IL or missing references) PlayerControllerB[] array = StartOfRound.Instance?.allPlayerScripts; if (array != null) { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append($"[DioDiag] HostHandleToggleRequest senderClientId={senderClientId}, IsPaused={PauseState.IsPaused}. Roster: "); for (int i = 0; i < array.Length; i++) { PlayerControllerB val = array[i]; if (!((Object)(object)val == (Object)null)) { stringBuilder.Append($"[idx={i} name={val.playerUsername} playerClientId={val.playerClientId} isPlayerControlled={val.isPlayerControlled} isOwner={((NetworkBehaviour)val).IsOwner}] "); } } Plugin.Log.LogInfo((object)stringBuilder.ToString()); } if (!PauseState.IsPaused) { if (HostPermissions.IsAllowed(senderClientId) && (!PauseState.CooldownEndsAtRealtime.TryGetValue(senderClientId, out var value) || !(Time.realtimeSinceStartup < value))) { PlayerControllerB val2 = FindPlayerByClientId(senderClientId); if (!((Object)(object)val2 == (Object)null)) { PauseStateData data = PauseStateData.Paused(senderClientId, ((Component)val2).transform.position, Plugin.PauseTimeLimitSeconds.Value); PauseState.PauseEndsAtRealtime = Time.realtimeSinceStartup + data.TimeLimit; PauseNetworking.BroadcastState(data); ApplyStateChange(data); } } } else if (senderClientId == PauseState.CasterClientId) { ResumeFromHost(); } } public static void ResumeFromHost() { PauseStateData data = PauseStateData.Resumed(); PauseState.CooldownEndsAtRealtime[PauseState.CasterClientId] = Time.realtimeSinceStartup + Plugin.PauseCooldownSeconds.Value; PauseNetworking.BroadcastState(data); ApplyStateChange(data); } public static void ApplyStateChange(PauseStateData data) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) PauseState.IsPaused = data.IsPaused; PauseState.CasterClientId = data.CasterClientId; if (data.IsPaused) { PlayerFreeze.ApplyIfNotExempt(data.CasterClientId); EnemyFreeze.Freeze(); TurretFreeze.Freeze(); SpikeTrapFreeze.Freeze(); ElevatorFreeze.Freeze(); MineFreeze.Freeze(); PauseEffects.StartPauseEffect(data.CasterPosition); ScanPulse.PlayAt(data.CasterPosition); } else { PlayerFreeze.RemoveFreeze(); EnemyFreeze.Unfreeze(); TurretFreeze.Unfreeze(); SpikeTrapFreeze.Unfreeze(); ElevatorFreeze.Unfreeze(); MineFreeze.Unfreeze(); PauseEffects.EndPauseEffect(); DamageQueue.ReplayAndClear(); MineQueue.ReplayAndClear(); PlayerDamageQueue.ReplayAndClear(); } } private static PlayerControllerB FindPlayerByClientId(ulong clientId) { PlayerControllerB[] array = StartOfRound.Instance?.allPlayerScripts; if (array == null) { return null; } PlayerControllerB[] array2 = array; foreach (PlayerControllerB val in array2) { if ((Object)(object)val != (Object)null && val.playerClientId == clientId) { return val; } } return null; } } public static class PauseEffects { private const float TransitionDuration = 0.6f; private static Volume _volume; private static ChromaticAberration _chromaticAberration; private static ColorAdjustments _colorAdjustments; private static bool _transitioning; private static float _transitionStart; private static float _startSaturation; private static float _endSaturation; private static float _startAberration; private static float _endAberration; public static void StartPauseEffect(Vector3 casterWorldPosition) { PauseAudio.PlayPause(); EnsureVolume(); BeginTransition(toGrey: true); } public static void EndPauseEffect() { PauseAudio.PlayResume(); EnsureVolume(); BeginTransition(toGrey: false); } public static void Tick() { if (_transitioning) { float num = Mathf.Clamp01((Time.unscaledTime - _transitionStart) / 0.6f); ((VolumeParameter<float>)(object)_colorAdjustments.saturation).value = Mathf.Lerp(_startSaturation, _endSaturation, num); ((VolumeParameter<float>)(object)_chromaticAberration.intensity).value = Mathf.Lerp(_startAberration, _endAberration, num); if (num >= 1f) { _transitioning = false; } } } private static void BeginTransition(bool toGrey) { _transitionStart = Time.unscaledTime; _startSaturation = ((VolumeParameter<float>)(object)_colorAdjustments.saturation).value; _endSaturation = (toGrey ? (-100f) : 0f); _startAberration = ((VolumeParameter<float>)(object)_chromaticAberration.intensity).value; _endAberration = (toGrey ? 1f : 0f); _transitioning = true; } private static void EnsureVolume() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown if (!((Object)(object)_volume != (Object)null)) { GameObject val = new GameObject("DioCompany_TimeStopVolume"); Object.DontDestroyOnLoad((Object)val); _volume = val.AddComponent<Volume>(); _volume.isGlobal = true; _volume.priority = 1000f; _volume.weight = 1f; VolumeProfile val2 = ScriptableObject.CreateInstance<VolumeProfile>(); _chromaticAberration = val2.Add<ChromaticAberration>(false); ((VolumeParameter<float>)(object)_chromaticAberration.intensity).value = 0f; ((VolumeParameter)_chromaticAberration.intensity).overrideState = true; _colorAdjustments = val2.Add<ColorAdjustments>(false); ((VolumeParameter<float>)(object)_colorAdjustments.saturation).value = 0f; ((VolumeParameter)_colorAdjustments.saturation).overrideState = true; _volume.profile = val2; Plugin.Log.LogInfo((object)"[PauseEffects] Created dedicated time-stop Volume."); } } } public static class PauseState { public static bool IsPaused; public static ulong CasterClientId; public static float PauseEndsAtRealtime; public static readonly Dictionary<ulong, float> CooldownEndsAtRealtime = new Dictionary<ulong, float>(); } public static class PlayerDamageQueue { private class Entry { public PlayerControllerB Target; public int Force; public Vector3 HitDirection; public PlayerControllerB PlayerWhoHit; public bool PlayHitSFX; public int HitId; } private static readonly MethodInfo HitMethod = ResolveHitMethod(); private static readonly List<Entry> Pending = new List<Entry>(); private static MethodInfo ResolveHitMethod() { InterfaceMapping interfaceMap = typeof(PlayerControllerB).GetInterfaceMap(typeof(IHittable)); int num = Array.IndexOf<MethodInfo>(interfaceMap.InterfaceMethods, typeof(IHittable).GetMethod("Hit")); if (num < 0) { return null; } return interfaceMap.TargetMethods[num]; } public static void Enqueue(PlayerControllerB target, int force, Vector3 hitDirection, PlayerControllerB playerWhoHit, bool playHitSFX, int hitId) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) Pending.Add(new Entry { Target = target, Force = force, HitDirection = hitDirection, PlayerWhoHit = playerWhoHit, PlayHitSFX = playHitSFX, HitId = hitId }); } public static void ReplayAndClear() { //IL_006e: Unknown result type (might be due to invalid IL or missing references) if (Pending.Count == 0 || HitMethod == null) { return; } List<Entry> list = new List<Entry>(Pending); Pending.Clear(); foreach (Entry item in list) { if (!((Object)(object)item.Target == (Object)null)) { HitMethod.Invoke(item.Target, new object[5] { item.Force, item.HitDirection, item.PlayerWhoHit, item.PlayHitSFX, item.HitId }); } } } } public static class PlayerFreeze { public static void ApplyIfNotExempt(ulong casterClientId) { PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if (!((Object)(object)val == (Object)null) && val.playerClientId != casterClientId) { val.disableMoveInput = true; val.disableLookInput = true; } } public static void RemoveFreeze() { PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if (!((Object)(object)val == (Object)null)) { val.disableMoveInput = false; val.disableLookInput = false; } } } [BepInPlugin("com.paul.diocompany.timestop", "Dio Company - Time Stop", "1.0.0")] public class Plugin : BaseUnityPlugin { public const string Guid = "com.paul.diocompany.timestop"; public const string Name = "Dio Company - Time Stop"; public const string Version = "1.0.0"; public static ConfigEntry<Key> PauseKey; public static ConfigEntry<float> PauseTimeLimitSeconds; public static ConfigEntry<float> PauseCooldownSeconds; public static ConfigEntry<string> ScanPulseColorHex; private Harmony _harmony; public static Plugin Instance { get; private set; } public static ManualLogSource Log { get; private set; } private void Awake() { //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; PauseKey = ((BaseUnityPlugin)this).Config.Bind<Key>("Keybinds", "PauseKey", (Key)24, "Requests a time-stop. Usable by the host, or by anyone the host has granted permission to (host types '/allow PlayerName' or '/deny PlayerName' in chat). Pressing it again while your own time-stop is active resumes it early."); PauseTimeLimitSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("General", "PauseTimeLimitSeconds", 30f, "Maximum duration, in seconds, a time-stop lasts before automatically resuming."); PauseCooldownSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("General", "PauseCooldownSeconds", 5f, "How long, in seconds, a given player must wait after ending their own time-stop before starting another. Per-player -- doesn't affect anyone else's cooldown."); ScanPulseColorHex = ((BaseUnityPlugin)this).Config.Bind<string>("Effects", "ScanPulseColorHex", "#FF33D9", "Hex color (e.g. #FF33D9) for the scan-pulse flash on time-stop cast. This is purely a local display preference -- it only changes what YOU see, regardless of who casts it."); _harmony = new Harmony("com.paul.diocompany.timestop"); _harmony.PatchAll(); PauseNetworking.Init(); PauseAudio.LoadClips(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Dio Company - Time Stop v1.0.0 loaded."); } } public static class ScanPulse { private const float PulseLifetime = 1.5f; private static readonly Color DefaultPulseColor = new Color(1f, 0.2f, 0.85f, 1f); private static readonly int[] ColorPropertyIds = new int[4] { Shader.PropertyToID("_Color"), Shader.PropertyToID("_BaseColor"), Shader.PropertyToID("_TintColor"), Shader.PropertyToID("_EmissionColor") }; private static Renderer[] _renderers; private static bool _tinted; private static float _untintAtRealtime; public static void PlayAt(Vector3 worldPosition) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) Animator val = (((Object)(object)HUDManager.Instance != (Object)null) ? HUDManager.Instance.scanEffectAnimator : null); if (!((Object)(object)val == (Object)null)) { if (_renderers == null) { _renderers = ((Component)val).GetComponentsInChildren<Renderer>(true); } MaterialPropertyBlock val2 = new MaterialPropertyBlock(); Color configuredColor = GetConfiguredColor(); int[] colorPropertyIds = ColorPropertyIds; foreach (int num in colorPropertyIds) { val2.SetColor(num, configuredColor); } Renderer[] renderers = _renderers; for (int i = 0; i < renderers.Length; i++) { renderers[i].SetPropertyBlock(val2); } ((Component)val).transform.position = worldPosition; val.SetTrigger("scan"); _tinted = true; _untintAtRealtime = Time.realtimeSinceStartup + 1.5f; } } public static void Tick() { if (_tinted && !(Time.realtimeSinceStartup < _untintAtRealtime)) { Renderer[] renderers = _renderers; for (int i = 0; i < renderers.Length; i++) { renderers[i].SetPropertyBlock((MaterialPropertyBlock)null); } _tinted = false; } } private static Color GetConfiguredColor() { //IL_001f: 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) string value = Plugin.ScanPulseColorHex.Value; Color result = default(Color); if (!string.IsNullOrEmpty(value) && ColorUtility.TryParseHtmlString(value, ref result)) { return result; } return DefaultPulseColor; } } public static class SpikeTrapFreeze { public static readonly List<SpikeRoofTrap> Active = new List<SpikeRoofTrap>(); public static void Freeze() { SetFrozen(frozen: true); } public static void Unfreeze() { SetFrozen(frozen: false); } private static void SetFrozen(bool frozen) { foreach (SpikeRoofTrap item in Active) { if (!((Object)(object)item == (Object)null)) { if ((Object)(object)item.spikeTrapAnimator != (Object)null) { item.spikeTrapAnimator.speed = (frozen ? 0f : 1f); } AudioSource[] componentsInChildren = ((Component)item).GetComponentsInChildren<AudioSource>(true); for (int i = 0; i < componentsInChildren.Length; i++) { componentsInChildren[i].mute = frozen; } } } } } public static class TurretFreeze { public static readonly List<Turret> Active = new List<Turret>(); public static void Freeze() { SetFrozen(frozen: true); } public static void Unfreeze() { SetFrozen(frozen: false); } private static void SetFrozen(bool frozen) { foreach (Turret item in Active) { if (!((Object)(object)item == (Object)null)) { if ((Object)(object)item.turretAnimator != (Object)null) { item.turretAnimator.speed = (frozen ? 0f : 1f); } AudioSource[] componentsInChildren = ((Component)item).GetComponentsInChildren<AudioSource>(true); for (int i = 0; i < componentsInChildren.Length; i++) { componentsInChildren[i].mute = frozen; } } } } } } namespace DioCompany.Patches { [HarmonyPatch(typeof(HUDManager), "AddTextToChatOnServer")] public static class ChatCommandPatch { private const string AllowPrefix = "/allow "; private const string DenyPrefix = "/deny "; [HarmonyPrefix] private static bool Prefix(string chatMessage) { if (chatMessage == null) { return true; } bool allow; string targetName; if (chatMessage.StartsWith("/allow ", StringComparison.OrdinalIgnoreCase)) { allow = true; targetName = chatMessage.Substring("/allow ".Length).Trim(); } else { if (!chatMessage.StartsWith("/deny ", StringComparison.OrdinalIgnoreCase)) { return true; } allow = false; targetName = chatMessage.Substring("/deny ".Length).Trim(); } HandleCommand(allow, targetName); return false; } private static void HandleCommand(bool allow, string targetName) { if ((Object)(object)NetworkManager.Singleton == (Object)null || !NetworkManager.Singleton.IsHost) { HUDManager instance = HUDManager.Instance; if (instance != null) { instance.DisplayTip("Time Stop", "Only the host can grant time-stop permission.", true, false, "LC_Tip1"); } return; } PlayerControllerB[] array = StartOfRound.Instance?.allPlayerScripts; if (array == null) { return; } PlayerControllerB[] array2 = array; foreach (PlayerControllerB val in array2) { if (!((Object)(object)val == (Object)null) && val.isPlayerControlled && string.Equals(val.playerUsername, targetName, StringComparison.OrdinalIgnoreCase)) { if (allow) { HostPermissions.AllowedClientIds.Add(val.playerClientId); } else { HostPermissions.AllowedClientIds.Remove(val.playerClientId); } HUDManager instance2 = HUDManager.Instance; if (instance2 != null) { instance2.DisplayTip("Time Stop", allow ? (val.playerUsername + " can now use time-stop.") : (val.playerUsername + "'s time-stop permission was revoked."), false, false, "LC_Tip1"); } return; } } HUDManager instance3 = HUDManager.Instance; if (instance3 != null) { instance3.DisplayTip("Time Stop", "No connected player found named '" + targetName + "'.", true, false, "LC_Tip1"); } } } [HarmonyPatch(typeof(MineshaftElevatorController))] public static class ElevatorFreezePatch { [HarmonyPatch("Update")] [HarmonyPrefix] private static bool UpdatePrefix() { return !PauseState.IsPaused; } [HarmonyPatch("LateUpdate")] [HarmonyPrefix] private static bool LateUpdatePrefix() { return !PauseState.IsPaused; } } [HarmonyPatch] public static class EnemyContactPatch { private static IEnumerable<MethodBase> TargetMethods() { Type[] types = typeof(EnemyAI).Assembly.GetTypes(); foreach (Type type in types) { if (typeof(EnemyAI).IsAssignableFrom(type)) { MethodInfo method = type.GetMethod("OnCollideWithPlayer", BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (method != null) { yield return method; } } } } [HarmonyPrefix] private static bool Prefix() { return !PauseState.IsPaused; } } [HarmonyPatch(typeof(EnemyAI), "HitEnemyOnLocalClient")] public static class EnemyDamagePatch { [HarmonyPrefix] private static bool Prefix(EnemyAI __instance, int force, Vector3 hitDirection, PlayerControllerB playerWhoHit, bool playHitSFX, int hitID) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) if (!PauseState.IsPaused) { return true; } PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if ((Object)(object)val == (Object)null || val.playerClientId != PauseState.CasterClientId) { return true; } DamageQueue.Enqueue(__instance, force, hitDirection, playerWhoHit, playHitSFX, hitID); return false; } } [HarmonyPatch] public static class EnemyLogicFreezePatch { private static readonly string[] MethodNames = new string[3] { "Update", "FixedUpdate", "LateUpdate" }; private static IEnumerable<MethodBase> TargetMethods() { Type[] types = typeof(EnemyAI).Assembly.GetTypes(); foreach (Type type in types) { if (!typeof(EnemyAI).IsAssignableFrom(type)) { continue; } string[] methodNames = MethodNames; foreach (string name in methodNames) { MethodInfo method = type.GetMethod(name, BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (method != null) { yield return method; } } } } [HarmonyPrefix] private static bool Prefix() { return !PauseState.IsPaused; } } [HarmonyPatch(typeof(Landmine), "TriggerMineOnLocalClientByExiting")] public static class MinePatch { [HarmonyPrefix] private static bool Prefix(Landmine __instance) { if (!PauseState.IsPaused) { return true; } MineQueue.Enqueue(__instance); return false; } } [HarmonyPatch(typeof(Landmine), "Start")] public static class MineRegistrationPatch { [HarmonyPostfix] private static void Postfix(Landmine __instance) { if (!MineFreeze.Active.Contains(__instance)) { MineFreeze.Active.Add(__instance); } } } [HarmonyPatch] public static class PlayerHitPatch { private static MethodBase TargetMethod() { InterfaceMapping interfaceMap = typeof(PlayerControllerB).GetInterfaceMap(typeof(IHittable)); int num = Array.IndexOf<MethodInfo>(interfaceMap.InterfaceMethods, typeof(IHittable).GetMethod("Hit")); if (num < 0) { return null; } return interfaceMap.TargetMethods[num]; } [HarmonyPrefix] private static bool Prefix(PlayerControllerB __instance, int force, Vector3 hitDirection, PlayerControllerB playerWhoHit, bool playHitSFX, int hitID, ref bool __result) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) if (!PauseState.IsPaused) { return true; } PlayerDamageQueue.Enqueue(__instance, force, hitDirection, playerWhoHit, playHitSFX, hitID); __result = true; return false; } } [HarmonyPatch(typeof(PlayerControllerB), "Update")] public static class PlayerTickPatch { [HarmonyPostfix] private static void Postfix(PlayerControllerB __instance) { PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if (!((Object)(object)val == (Object)null) && !((Object)(object)__instance != (Object)(object)val)) { ModTick.Tick(); } } } [HarmonyPatch(typeof(SpikeRoofTrap))] public static class SpikeTrapFreezePatch { [HarmonyPatch("Update")] [HarmonyPrefix] private static bool UpdatePrefix() { return !PauseState.IsPaused; } [HarmonyPatch("OnTriggerStay")] [HarmonyPrefix] private static bool OnTriggerStayPrefix() { return !PauseState.IsPaused; } } [HarmonyPatch(typeof(SpikeRoofTrap), "Start")] public static class SpikeTrapRegistrationPatch { [HarmonyPostfix] private static void Postfix(SpikeRoofTrap __instance) { if (!SpikeTrapFreeze.Active.Contains(__instance)) { SpikeTrapFreeze.Active.Add(__instance); } } } [HarmonyPatch(typeof(TimeOfDay), "MoveTimeOfDay")] public static class TimeOfDayPatch { [HarmonyPrefix] private static bool Prefix() { return !PauseState.IsPaused; } } [HarmonyPatch(typeof(Turret), "Update")] public static class TurretFreezePatch { [HarmonyPrefix] private static bool Prefix() { return !PauseState.IsPaused; } } [HarmonyPatch(typeof(Turret), "Start")] public static class TurretRegistrationPatch { [HarmonyPostfix] private static void Postfix(Turret __instance) { if (!TurretFreeze.Active.Contains(__instance)) { TurretFreeze.Active.Add(__instance); } } } } namespace DioCompany.Networking { [Serializable] public struct PauseStateData { public bool IsPaused; public ulong CasterClientId; public float CasterPosX; public float CasterPosY; public float CasterPosZ; public float TimeLimit; public Vector3 CasterPosition => new Vector3(CasterPosX, CasterPosY, CasterPosZ); public static PauseStateData Paused(ulong casterClientId, Vector3 casterPosition, float timeLimit) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) return new PauseStateData { IsPaused = true, CasterClientId = casterClientId, CasterPosX = casterPosition.x, CasterPosY = casterPosition.y, CasterPosZ = casterPosition.z, TimeLimit = timeLimit }; } public static PauseStateData Resumed() { return new PauseStateData { IsPaused = false }; } } public static class PauseNetworking { private static LNetworkMessage<bool> _toggleRequest; private static LNetworkMessage<PauseStateData> _stateChanged; private static bool _initialized; public static void Init() { if (!_initialized) { _initialized = true; _toggleRequest = LNetworkMessage<bool>.Connect("ToggleRequest", (Action<bool, ulong>)delegate(bool _, ulong senderClientId) { PauseController.HostHandleToggleRequest(senderClientId); }, (Action<bool>)null, (Action<bool, ulong>)null); _stateChanged = LNetworkMessage<PauseStateData>.Connect("PauseStateChanged", (Action<PauseStateData, ulong>)null, (Action<PauseStateData>)PauseController.ApplyStateChange, (Action<PauseStateData, ulong>)null); } } public static void RequestToggle() { _toggleRequest.SendServer(true); } public static void BroadcastState(PauseStateData data) { _stateChanged.SendClients(data); } } }