Decompiled source of TornadoFix v1.0.1

TornadoFix.dll

Decompiled a day ago
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 <RetryPrefabRegistration>d__9 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public TornadoFixPlugin <>4__this;

			private int <i>5__1;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <RetryPrefabRegistration>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();
					<i>5__1++;
				}
				else
				{
					<>1__state = -1;
					<i>5__1 = 0;
				}
				if (<i>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<int> WarnedTornadoes = new HashSet<int>();

		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<GameObject>("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>("");
					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<Tornado>();
					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(<RetryPrefabRegistration>d__9))]
		private IEnumerator RetryPrefabRegistration()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <RetryPrefabRegistration>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<Character>();
			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<Character> list)
			{
				list.Clear();
			}
			if (ignoredField != null && ignoredField.GetValue(__instance) is List<Character> 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<TornadoSpawner>();
			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<PhotonView>();
				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<PhotonView>();
			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;
		}
	}
}