using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using Photon.Pun; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("TornadoFix")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+ac03db15e7e884e25c1929b7160a459032d52b45")] [assembly: AssemblyProduct("TornadoFix")] [assembly: AssemblyTitle("TornadoFix")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } 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; } } [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; } } [CompilerGenerated] [Microsoft.CodeAnalysis.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 TornadoFix { [BepInPlugin("jill920.tornadofix", "Tornado Fix", "1.0.1")] public class TornadoFixPlugin : BaseUnityPlugin { [CompilerGenerated] private sealed class d__9 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public TornadoFixPlugin <>4__this; private int 5__1; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__9(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Expected O, but got Unknown int num = <>1__state; if (num != 0) { if (num != 1) { return false; } <>1__state = -1; if (prefabRegistered) { goto IL_0088; } <>4__this.ForceRegisterTornadoPrefab(); 5__1++; } else { <>1__state = -1; 5__1 = 0; } if (5__1 < 12) { <>2__current = (object)new WaitForSeconds(5f); <>1__state = 1; return true; } goto IL_0088; IL_0088: return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } public const string MOD_GUID = "jill920.tornadofix"; public const string MOD_NAME = "Tornado Fix"; public const string MOD_VERSION = "1.0.1"; public static ManualLogSource Logger; public static bool DebugMode = false; internal static HashSet WarnedTornadoes = new HashSet(); private static bool prefabRegistered = false; private void Awake() { Logger = ((BaseUnityPlugin)this).Logger; string[] commandLineArgs = Environment.GetCommandLineArgs(); string[] array = commandLineArgs; foreach (string text in array) { if (text.Equals("-TornadoDebug", StringComparison.OrdinalIgnoreCase)) { DebugMode = true; break; } } ForceRegisterTornadoPrefab(); Harmony.CreateAndPatchAll(typeof(TornadoFixPatches), (string)null); Logger.LogInfo((object)"[Tornado Fix 1.0.1] Loaded - Fixing tornado issues"); } private void ForceRegisterTornadoPrefab() { if (prefabRegistered) { return; } try { GameObject val = null; val = Resources.Load("Tornado"); if ((Object)(object)val != (Object)null) { Logger.LogInfo((object)"Found Tornado prefab via Resources.Load"); } if ((Object)(object)val == (Object)null) { GameObject[] array = Resources.LoadAll(""); GameObject[] array2 = array; foreach (GameObject val2 in array2) { if ((Object)(object)val2 != (Object)null && ((Object)val2).name == "Tornado") { val = val2; Logger.LogInfo((object)"Found Tornado prefab via Resources.LoadAll"); break; } } } if ((Object)(object)val == (Object)null) { Tornado val3 = Object.FindObjectOfType(); if ((Object)(object)val3 != (Object)null) { Logger.LogInfo((object)"Tornado instance found in scene - prefab should be registered"); prefabRegistered = true; return; } } if ((Object)(object)val != (Object)null) { IPunPrefabPool prefabPool = PhotonNetwork.PrefabPool; DefaultPool val4 = (DefaultPool)(object)((prefabPool is DefaultPool) ? prefabPool : null); if (val4 != null) { if (!val4.ResourceCache.ContainsKey("Tornado")) { val4.ResourceCache["Tornado"] = val; prefabRegistered = true; Logger.LogInfo((object)"Successfully registered Tornado prefab with Photon"); } else { prefabRegistered = true; Logger.LogInfo((object)"Tornado prefab already registered with Photon"); } } else { Logger.LogWarning((object)"Could not access Photon PrefabPool - spawns may fail"); } } else { Logger.LogWarning((object)"Tornado prefab not found - spawns will be delayed until natural tornado loads it"); ((MonoBehaviour)this).StartCoroutine(RetryPrefabRegistration()); } } catch (Exception ex) { Logger.LogError((object)("Failed to register Tornado prefab: " + ex.Message)); } } [IteratorStateMachine(typeof(d__9))] private IEnumerator RetryPrefabRegistration() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__9(0) { <>4__this = this }; } private void Update() { if (!prefabRegistered && PhotonNetwork.InRoom) { ForceRegisterTornadoPrefab(); } } } [HarmonyPatch] internal static class TornadoFixPatches { private static FieldInfo targetParentField; private static FieldInfo caughtField; private static FieldInfo ignoredField; private static FieldInfo viewField; static TornadoFixPatches() { targetParentField = typeof(Tornado).GetField("targetParent", BindingFlags.Instance | BindingFlags.NonPublic); caughtField = typeof(Tornado).GetField("caughtCharacters", BindingFlags.Instance | BindingFlags.NonPublic); ignoredField = typeof(Tornado).GetField("ignoredCharacters", BindingFlags.Instance | BindingFlags.NonPublic); viewField = typeof(Tornado).GetField("view", BindingFlags.Instance | BindingFlags.NonPublic); } [HarmonyPatch(typeof(Tornado), "RPCA_ThrowPlayer")] [HarmonyPrefix] private static bool Prefix_RPCA_ThrowPlayer(Tornado __instance, int targetView) { PhotonView val = PhotonView.Find(targetView); if ((Object)(object)val == (Object)null) { if (TornadoFixPlugin.DebugMode) { TornadoFixPlugin.Logger.LogWarning((object)$"RPCA_ThrowPlayer: Could not find PhotonView with ID {targetView}"); } return false; } Character component = ((Component)val).GetComponent(); if ((Object)(object)component == (Object)null) { if (TornadoFixPlugin.DebugMode) { TornadoFixPlugin.Logger.LogWarning((object)$"RPCA_ThrowPlayer: Character component not found on view {targetView}"); } return false; } return true; } [HarmonyPatch(typeof(Tornado), "RPCA_TornadoDie")] [HarmonyPostfix] private static void Postfix_RPCA_TornadoDie(Tornado __instance) { if (caughtField != null && caughtField.GetValue(__instance) is List list) { list.Clear(); } if (ignoredField != null && ignoredField.GetValue(__instance) is List list2) { list2.Clear(); } if (TornadoFixPlugin.DebugMode) { TornadoFixPlugin.Logger.LogDebug((object)"Tornado lists cleared on death"); } } [HarmonyPatch(typeof(Tornado), "PickTarget")] [HarmonyPrefix] private static bool Prefix_PickTarget(Tornado __instance) { object? obj = targetParentField?.GetValue(__instance); Transform val = (Transform)((obj is Transform) ? obj : null); if ((Object)(object)val == (Object)null) { int instanceID = ((Object)__instance).GetInstanceID(); if (!TornadoFixPlugin.WarnedTornadoes.Contains(instanceID)) { TornadoFixPlugin.WarnedTornadoes.Add(instanceID); TornadoFixPlugin.Logger.LogWarning((object)$"PickTarget: targetParent is null for tornado {instanceID} - auto-initializing"); TryInitializeTornado(__instance); } return false; } if (val.childCount == 0) { if (TornadoFixPlugin.DebugMode) { TornadoFixPlugin.Logger.LogDebug((object)$"PickTarget: targetParent has no children for tornado {((Object)__instance).GetInstanceID()}"); } return false; } return true; } private static void TryInitializeTornado(Tornado tornado) { TornadoSpawner val = Object.FindObjectOfType(); if ((Object)(object)val == (Object)null) { return; } Transform val2 = ((Component)val).transform.Find("TornadoPoints"); if (!((Object)(object)val2 == (Object)null)) { targetParentField?.SetValue(tornado, val2); PhotonView component = ((Component)tornado).GetComponent(); if ((Object)(object)component != (Object)null && viewField != null) { viewField.SetValue(tornado, component); } TornadoFixPlugin.Logger.LogInfo((object)$"Auto-initialized tornado {((Object)tornado).GetInstanceID()} with {val2.childCount} target points"); } } [HarmonyPatch(typeof(Tornado), "RPCA_InitTornado")] [HarmonyPrefix] private static bool Prefix_RPCA_InitTornado(Tornado __instance, int targetViewID) { PhotonView val = PhotonView.Find(targetViewID); if ((Object)(object)val == (Object)null) { TornadoFixPlugin.Logger.LogWarning((object)$"RPCA_InitTornado: Could not find spawner view with ID {targetViewID}"); return false; } Transform val2 = ((Component)val).transform.Find("TornadoPoints"); if ((Object)(object)val2 == (Object)null) { TornadoFixPlugin.Logger.LogWarning((object)"RPCA_InitTornado: TornadoPoints not found on spawner"); return false; } targetParentField?.SetValue(__instance, val2); PhotonView component = ((Component)__instance).GetComponent(); if ((Object)(object)component != (Object)null && viewField != null) { viewField.SetValue(__instance, component); } int instanceID = ((Object)__instance).GetInstanceID(); if (TornadoFixPlugin.WarnedTornadoes.Contains(instanceID)) { TornadoFixPlugin.WarnedTornadoes.Remove(instanceID); } if (TornadoFixPlugin.DebugMode) { TornadoFixPlugin.Logger.LogDebug((object)$"Tornado initialized with {val2.childCount} target points"); } return false; } [HarmonyPatch(typeof(TornadoSpawner), "SpawnTornado")] [HarmonyPrefix] private static bool Prefix_SpawnTornado(TornadoSpawner __instance) { if (!PhotonNetwork.IsMasterClient) { return false; } if (TornadoFixPlugin.DebugMode) { TornadoFixPlugin.Logger.LogDebug((object)"Spawning tornado"); } return true; } } }