Decompiled source of Green Shell v1.0.0

BepInEx/plugins/Omniscye-Empress_GreenShell/EmpressGreenShell.dll

Decompiled 10 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using ExitGames.Client.Photon;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using Photon.Realtime;
using REPOLib.Modules;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Networking;

[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("Empress")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("EmpressGreenShell")]
[assembly: AssemblyTitle("EmpressGreenShell")]
[assembly: AssemblyVersion("1.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 Empress.REPO.GreenShell
{
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInPlugin("com.empress.repo.greenshell", "Empress Green Shell", "1.0.0")]
	public sealed class EmpressGreenShellPlugin : BaseUnityPlugin
	{
		public const string PluginGuid = "com.empress.repo.greenshell";

		public const string PluginName = "Empress Green Shell";

		public const string PluginVersion = "1.0.0";

		public const string ItemName = "Empress Green Shell";

		internal const byte ShellSpawnEventCode = 190;

		internal const byte ShellSyncEventCode = 191;

		internal const byte ShellEndEventCode = 192;

		internal const byte ShellBounceEventCode = 193;

		private static bool _photonHooked;

		private static LoadBalancingClient _hookedClient;

		private Harmony _harmony;

		internal static EmpressGreenShellPlugin Instance { get; private set; }

		internal static ManualLogSource Log { get; private set; }

		internal static GreenShellSettings Settings { get; private set; }

		internal static string PluginDirectory { get; private set; }

		private void Awake()
		{
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			PluginDirectory = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location);
			Settings = new GreenShellSettings(((BaseUnityPlugin)this).Config);
			((Component)this).gameObject.transform.parent = null;
			((Object)((Component)this).gameObject).hideFlags = (HideFlags)61;
			Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
			GreenShellAssets.Load();
			GreenShellItemBuilder.RegisterItem();
			_harmony = new Harmony("com.empress.repo.greenshell");
			_harmony.PatchAll(typeof(EmpressGreenShellPlugin).Assembly);
			GreenShellRuntime.EnsureHost();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Empress Green Shell v1.0.0 loaded.");
		}

		private void OnDestroy()
		{
			RemovePhotonHook();
		}

		internal static void EnsurePhotonHooked()
		{
			LoadBalancingClient networkingClient = PhotonNetwork.NetworkingClient;
			if (networkingClient != null && (!_photonHooked || _hookedClient != networkingClient))
			{
				if (_hookedClient != null)
				{
					_hookedClient.EventReceived -= OnPhotonEvent;
				}
				networkingClient.EventReceived -= OnPhotonEvent;
				networkingClient.EventReceived += OnPhotonEvent;
				_hookedClient = networkingClient;
				_photonHooked = true;
			}
		}

		internal static void RemovePhotonHook()
		{
			if (_hookedClient != null)
			{
				_hookedClient.EventReceived -= OnPhotonEvent;
			}
			_hookedClient = null;
			_photonHooked = false;
		}

		private static void OnPhotonEvent(EventData ev)
		{
			if (!(ev.CustomData is object[] data))
			{
				return;
			}
			GreenShellRuntime instance = GreenShellRuntime.Instance;
			if (!((Object)(object)instance == (Object)null))
			{
				if (ev.Code == 190)
				{
					instance.ReceiveShellSpawn(data);
				}
				else if (ev.Code == 191)
				{
					instance.ReceiveShellSync(data);
				}
				else if (ev.Code == 192)
				{
					instance.ReceiveShellEnd(data);
				}
				else if (ev.Code == 193)
				{
					instance.ReceiveShellBounce(data);
				}
			}
		}

		internal static void RaiseToAll(byte code, object[] data)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			EnsurePhotonHooked();
			if (!PhotonNetwork.InRoom)
			{
				OnPhotonEventLocal(code, data);
				return;
			}
			RaiseEventOptions val = new RaiseEventOptions
			{
				Receivers = (ReceiverGroup)1
			};
			PhotonNetwork.RaiseEvent(code, (object)data, val, SendOptions.SendReliable);
		}

		internal static void RaiseUnreliable(byte code, object[] data)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Expected O, but got Unknown
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			if (PhotonNetwork.InRoom)
			{
				RaiseEventOptions val = new RaiseEventOptions
				{
					Receivers = (ReceiverGroup)1
				};
				PhotonNetwork.RaiseEvent(code, (object)data, val, SendOptions.SendUnreliable);
			}
		}

		internal static void RaiseOthersUnreliable(byte code, object[] data)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Expected O, but got Unknown
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			if (PhotonNetwork.InRoom)
			{
				RaiseEventOptions val = new RaiseEventOptions
				{
					Receivers = (ReceiverGroup)0
				};
				PhotonNetwork.RaiseEvent(code, (object)data, val, SendOptions.SendUnreliable);
			}
		}

		private static void OnPhotonEventLocal(byte code, object[] data)
		{
			GreenShellRuntime instance = GreenShellRuntime.Instance;
			if (!((Object)(object)instance == (Object)null))
			{
				switch (code)
				{
				case 190:
					instance.ReceiveShellSpawn(data);
					break;
				case 192:
					instance.ReceiveShellEnd(data);
					break;
				}
			}
		}
	}
	internal sealed class GreenShellSettings
	{
		public readonly ConfigEntry<int> PriceThousands;

		public readonly ConfigEntry<float> Lifetime;

		public readonly ConfigEntry<float> Speed;

		public readonly ConfigEntry<float> PlayerFling;

		public readonly ConfigEntry<float> EnemyFling;

		public readonly ConfigEntry<float> HitVolume;

		public GreenShellSettings(ConfigFile config)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Expected O, but got Unknown
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Expected O, but got Unknown
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Expected O, but got Unknown
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: 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_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Expected O, but got Unknown
			PriceThousands = config.Bind<int>("Shell", "PriceThousands", 5, new ConfigDescription("Shop price in thousands of K. 5 means 5,000.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 500), Array.Empty<object>()));
			Lifetime = config.Bind<float>("Shell", "Lifetime", 30f, new ConfigDescription("Seconds the shell roams before it vanishes.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 90f), Array.Empty<object>()));
			Speed = config.Bind<float>("Shell", "Speed", 7f, new ConfigDescription("How fast the shell travels.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 16f), Array.Empty<object>()));
			PlayerFling = config.Bind<float>("Shell", "PlayerFling", 9f, new ConfigDescription("How hard players get flung when hit.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 25f), Array.Empty<object>()));
			EnemyFling = config.Bind<float>("Shell", "EnemyFling", 12f, new ConfigDescription("How hard enemies get flung when hit.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 40f), Array.Empty<object>()));
			HitVolume = config.Bind<float>("Audio", "HitVolume", 0.32f, new ConfigDescription("Volume of the shell bounce sound. Kept low on purpose.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
		}
	}
	internal static class GreenShellAccess
	{
		private static readonly FieldInfo ItemLocalizedNameField = AccessTools.Field(typeof(Item), "itemNameLocalized");

		private static readonly FieldRef<ItemAttributes, string> ItemNameRef = AccessTools.FieldRefAccess<ItemAttributes, string>("itemName");

		private static readonly FieldRef<ItemAttributes, string> InstanceNameRef = AccessTools.FieldRefAccess<ItemAttributes, string>("instanceName");

		private static readonly FieldRef<PlayerController, float> InputDisableTimerRef = AccessTools.FieldRefAccess<PlayerController, float>("InputDisableTimer");

		private static readonly FieldRef<PhysGrabObject, bool> HeldByLocalRef = AccessTools.FieldRefAccess<PhysGrabObject, bool>("heldByLocalPlayer");

		internal static bool InputAllowed()
		{
			if ((Object)(object)PlayerController.instance != (Object)null)
			{
				return InputDisableTimerRef.Invoke(PlayerController.instance) <= 0f;
			}
			return false;
		}

		internal static bool HeldByLocal(PhysGrabObject grab)
		{
			if ((Object)(object)grab != (Object)null)
			{
				return HeldByLocalRef.Invoke(grab);
			}
			return false;
		}

		internal static void SetItemName(ItemAttributes attributes, string name)
		{
			if (!((Object)(object)attributes == (Object)null))
			{
				ItemNameRef.Invoke(attributes) = name;
				InstanceNameRef.Invoke(attributes) = name;
			}
		}

		internal static string InstanceName(ItemAttributes attributes)
		{
			if (!((Object)(object)attributes != (Object)null))
			{
				return null;
			}
			return InstanceNameRef.Invoke(attributes);
		}

		internal static void ClearLocalizedName(Item item)
		{
			if ((Object)(object)item != (Object)null)
			{
				ItemLocalizedNameField?.SetValue(item, null);
			}
		}

		internal static PlayerAvatar LocalAvatar()
		{
			if (!((Object)(object)PlayerController.instance != (Object)null))
			{
				return null;
			}
			return PlayerController.instance.playerAvatarScript;
		}

		internal static List<PlayerAvatar> Players()
		{
			if (!((Object)(object)GameDirector.instance != (Object)null) || GameDirector.instance.PlayerList == null)
			{
				return new List<PlayerAvatar>();
			}
			return GameDirector.instance.PlayerList;
		}

		internal static PlayerAvatar AvatarByViewId(int viewId)
		{
			List<PlayerAvatar> list = Players();
			for (int i = 0; i < list.Count; i++)
			{
				if ((Object)(object)list[i] != (Object)null && (Object)(object)list[i].photonView != (Object)null && list[i].photonView.ViewID == viewId)
				{
					return list[i];
				}
			}
			return null;
		}
	}
	internal static class GreenShellAssets
	{
		private const string BundleFile = "empressgreenshell.empress";

		private const string PrefabName = "EmpressGreenShell";

		private static AssetBundle _bundle;

		private static bool _loaded;

		private static readonly Dictionary<string, AudioClip> Clips = new Dictionary<string, AudioClip>(StringComparer.OrdinalIgnoreCase);

		internal static GameObject ShellPrefab { get; private set; }

		internal static bool HasClips => Clips.Count > 0;

		internal static AudioClip Clip(string name)
		{
			Clips.TryGetValue(name, out var value);
			return value;
		}

		internal static void Load()
		{
			if (_loaded)
			{
				return;
			}
			_loaded = true;
			string text = Path.Combine(EmpressGreenShellPlugin.PluginDirectory ?? string.Empty, "bundles", "empressgreenshell.empress");
			if (File.Exists(text))
			{
				_bundle = AssetBundle.LoadFromFile(text);
				ShellPrefab = (((Object)(object)_bundle != (Object)null) ? _bundle.LoadAsset<GameObject>("EmpressGreenShell") : null);
				if ((Object)(object)ShellPrefab == (Object)null && (Object)(object)_bundle != (Object)null)
				{
					string text2 = _bundle.GetAllAssetNames().FirstOrDefault((string name) => name.EndsWith(".prefab"));
					if (!string.IsNullOrEmpty(text2))
					{
						ShellPrefab = _bundle.LoadAsset<GameObject>(text2);
					}
				}
			}
			else
			{
				ManualLogSource log = EmpressGreenShellPlugin.Log;
				if (log != null)
				{
					log.LogError((object)("Empress Green Shell bundle missing: " + text));
				}
			}
			ManualLogSource log2 = EmpressGreenShellPlugin.Log;
			if (log2 != null)
			{
				log2.LogInfo((object)("Empress Green Shell assets loaded. Shell: " + (((Object)(object)ShellPrefab != (Object)null) ? ((Object)ShellPrefab).name : "MISSING")));
			}
		}

		internal static IEnumerator LoadAudio()
		{
			string path = Path.Combine(EmpressGreenShellPlugin.PluginDirectory ?? string.Empty, "audio");
			if (!Directory.Exists(path))
			{
				yield break;
			}
			string[] files = Directory.GetFiles(path, "*.ogg");
			foreach (string text in files)
			{
				string key = Path.GetFileNameWithoutExtension(text);
				UnityWebRequest request = UnityWebRequestMultimedia.GetAudioClip("file://" + text, (AudioType)14);
				try
				{
					yield return request.SendWebRequest();
					if ((int)request.result == 1)
					{
						AudioClip content = DownloadHandlerAudioClip.GetContent(request);
						if ((Object)(object)content != (Object)null)
						{
							((Object)content).name = key;
							Clips[key] = content;
						}
					}
				}
				finally
				{
					((IDisposable)request)?.Dispose();
				}
			}
			ManualLogSource log = EmpressGreenShellPlugin.Log;
			if (log != null)
			{
				log.LogInfo((object)("Empress Green Shell audio loaded: " + Clips.Count + " clips."));
			}
		}
	}
	internal sealed class GreenShellItem : MonoBehaviour
	{
		private PhysGrabObject _grab;

		private PhotonView _view;

		private bool _used;

		private void Awake()
		{
			_grab = ((Component)this).GetComponent<PhysGrabObject>();
			_view = ((Component)this).GetComponent<PhotonView>();
		}

		private void Update()
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			if (_used || (Object)(object)_grab == (Object)null || !GreenShellAccess.HeldByLocal(_grab) || !GreenShellAccess.InputAllowed() || !SemiFunc.InputDown((InputKey)2))
			{
				return;
			}
			PlayerAvatar val = GreenShellAccess.LocalAvatar();
			if (!((Object)(object)val == (Object)null) && !((Object)(object)val.photonView == (Object)null))
			{
				Vector3 forward = ((Component)val).transform.forward;
				forward.y = 0f;
				if (((Vector3)(ref forward)).sqrMagnitude < 0.001f)
				{
					forward = Vector3.forward;
				}
				((Vector3)(ref forward)).Normalize();
				Vector3 val2 = ((Component)val).transform.position + forward * 1.2f + Vector3.up * 0.4f;
				_used = true;
				int viewID = val.photonView.ViewID;
				int num = (((Object)(object)_view != (Object)null) ? _view.ViewID : (-1));
				EmpressGreenShellPlugin.EnsurePhotonHooked();
				EmpressGreenShellPlugin.RaiseToAll(190, new object[8] { viewID, num, val2.x, val2.y, val2.z, forward.x, forward.y, forward.z });
				Renderer[] componentsInChildren = ((Component)this).GetComponentsInChildren<Renderer>(true);
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					componentsInChildren[i].enabled = false;
				}
			}
		}
	}
	internal static class GreenShellItemBuilder
	{
		private static readonly string[] TemplatePaths = new string[4] { "Items/Item Grenade Human", "Items/Item Grenade Explosive", "Items/Item Grenade Stun", "Items/Item Grenade Duct Taped" };

		private static GameObject _prefab;

		private static Item _item;

		private static bool _registered;

		internal static void RegisterItem()
		{
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Expected O, but got Unknown
			//IL_0254: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			if (_registered)
			{
				return;
			}
			GameObject val = null;
			for (int i = 0; i < TemplatePaths.Length; i++)
			{
				val = Resources.Load<GameObject>(TemplatePaths[i]);
				if ((Object)(object)val != (Object)null)
				{
					break;
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				EmpressGreenShellPlugin.Log.LogError((object)"Empress Green Shell could not find a template item.");
				return;
			}
			ItemAttributes component = val.GetComponent<ItemAttributes>();
			if ((Object)(object)component == (Object)null || (Object)(object)component.item == (Object)null)
			{
				EmpressGreenShellPlugin.Log.LogError((object)"Empress Green Shell template has no ItemAttributes.");
				return;
			}
			GameObject val2 = new GameObject("Empress Green Shell Prefabs");
			Object.DontDestroyOnLoad((Object)(object)val2);
			((Object)val2).hideFlags = (HideFlags)61;
			val2.SetActive(false);
			_prefab = Object.Instantiate<GameObject>(val, val2.transform);
			((Object)_prefab).name = "Empress Green Shell";
			MonoBehaviour[] componentsInChildren = _prefab.GetComponentsInChildren<MonoBehaviour>(true);
			foreach (MonoBehaviour val3 in componentsInChildren)
			{
				if (!((Object)(object)val3 == (Object)null))
				{
					string name = ((object)val3).GetType().Name;
					if (name.StartsWith("ItemGrenade") || name == "ItemToggle" || name == "ItemBattery")
					{
						Object.DestroyImmediate((Object)(object)val3);
					}
				}
			}
			Renderer[] componentsInChildren2 = _prefab.GetComponentsInChildren<Renderer>(true);
			for (int j = 0; j < componentsInChildren2.Length; j++)
			{
				componentsInChildren2[j].enabled = false;
			}
			if ((Object)(object)GreenShellAssets.ShellPrefab != (Object)null)
			{
				GameObject val4 = Object.Instantiate<GameObject>(GreenShellAssets.ShellPrefab, _prefab.transform, false);
				((Object)val4).name = "Empress Green Shell Visual";
				val4.transform.localPosition = Vector3.zero;
				val4.transform.localRotation = Quaternion.identity;
				ScaleToSize(val4, 0.32f);
				Collider[] componentsInChildren3 = val4.GetComponentsInChildren<Collider>(true);
				for (int j = 0; j < componentsInChildren3.Length; j++)
				{
					Object.DestroyImmediate((Object)(object)componentsInChildren3[j]);
				}
				componentsInChildren2 = val4.GetComponentsInChildren<Renderer>(true);
				for (int j = 0; j < componentsInChildren2.Length; j++)
				{
					componentsInChildren2[j].enabled = true;
				}
			}
			_prefab.AddComponent<GreenShellItem>();
			Item item = component.item;
			_item = Object.Instantiate<Item>(item);
			((Object)_item).name = "Empress Green Shell";
			_item.itemName = "Empress Green Shell";
			GreenShellAccess.ClearLocalizedName(_item);
			_item.itemSecretShopType = (itemSecretShopType)0;
			_item.maxAmount = 5;
			_item.maxAmountInShop = 3;
			_item.maxPurchase = false;
			_item.maxPurchaseAmount = 5;
			float value = (float)EmpressGreenShellPlugin.Settings.PriceThousands.Value * 1000f;
			Value val5 = (((Object)(object)item.value != (Object)null) ? Object.Instantiate<Value>(item.value) : ScriptableObject.CreateInstance<Value>());
			SetFloatFieldContaining(val5, "min", value);
			SetFloatFieldContaining(val5, "max", value);
			_item.value = val5;
			ItemAttributes component2 = _prefab.GetComponent<ItemAttributes>();
			component2.item = _item;
			GreenShellAccess.SetItemName(component2, "Empress Green Shell");
			_registered = Items.RegisterItem(component2) != null;
			EmpressGreenShellPlugin.Log.LogInfo((object)("Empress Green Shell item registered: " + _registered));
		}

		internal static void ScaleToSize(GameObject target, float maxDimension)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			Bounds bounds = default(Bounds);
			((Bounds)(ref bounds))..ctor(target.transform.position, Vector3.zero);
			bool flag = false;
			Renderer[] componentsInChildren = target.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val in componentsInChildren)
			{
				if (!flag)
				{
					bounds = val.bounds;
					flag = true;
				}
				else
				{
					((Bounds)(ref bounds)).Encapsulate(val.bounds);
				}
			}
			if (flag)
			{
				float num = Mathf.Max(((Bounds)(ref bounds)).size.x, Mathf.Max(((Bounds)(ref bounds)).size.y, ((Bounds)(ref bounds)).size.z));
				if (!(num <= 0.0001f))
				{
					float num2 = maxDimension / num;
					target.transform.localScale = target.transform.localScale * num2;
				}
			}
		}

		private static void SetFloatFieldContaining(object target, string token, float value)
		{
			if (target == null)
			{
				return;
			}
			FieldInfo[] fields = target.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			foreach (FieldInfo fieldInfo in fields)
			{
				if (fieldInfo.FieldType == typeof(float) && fieldInfo.Name.ToLowerInvariant().Contains(token))
				{
					fieldInfo.SetValue(target, value);
				}
			}
		}
	}
	internal sealed class GreenShellRuntime : MonoBehaviour
	{
		private sealed class Shell
		{
			internal int ShellId;

			internal GameObject Go;

			internal Transform Model;

			internal Vector3 Dir;

			internal double EndTime;

			internal float SyncTimer;

			internal Vector3 TargetPos;

			internal bool HasTarget;

			internal AudioSource Audio;

			internal float SoundCooldown;
		}

		private const float ColliderRadius = 0.55f;

		private const float ShellSize = 0.62f;

		private const float SyncInterval = 0.08f;

		private readonly List<Shell> _shells = new List<Shell>();

		private int _geometryMask;

		public static GreenShellRuntime Instance { get; private set; }

		public static GreenShellRuntime EnsureHost()
		{
			//IL_0018: 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)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Expected O, but got Unknown
			if ((Object)(object)Instance != (Object)null)
			{
				return Instance;
			}
			GameObject val = new GameObject("Empress Green Shell Runtime");
			val.transform.parent = null;
			((Object)val).hideFlags = (HideFlags)61;
			Object.DontDestroyOnLoad((Object)val);
			Instance = val.AddComponent<GreenShellRuntime>();
			return Instance;
		}

		private void Awake()
		{
			Instance = this;
			_geometryMask = LayerMask.GetMask(new string[1] { "Default" });
			((MonoBehaviour)this).StartCoroutine(GreenShellAssets.LoadAudio());
		}

		private void Update()
		{
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			EmpressGreenShellPlugin.EnsurePhotonHooked();
			float deltaTime = Time.deltaTime;
			bool flag = SemiFunc.IsMasterClientOrSingleplayer();
			float value = EmpressGreenShellPlugin.Settings.Speed.Value;
			double num = NetworkNow();
			for (int num2 = _shells.Count - 1; num2 >= 0; num2--)
			{
				Shell shell = _shells[num2];
				if ((Object)(object)shell.Go == (Object)null)
				{
					_shells.RemoveAt(num2);
					continue;
				}
				if (shell.SoundCooldown > 0f)
				{
					shell.SoundCooldown -= deltaTime;
				}
				if (flag)
				{
					Simulate(shell, deltaTime, value);
					shell.SyncTimer -= deltaTime;
					if (shell.SyncTimer <= 0f)
					{
						shell.SyncTimer = 0.08f;
						BroadcastSync(shell);
					}
					if (num >= shell.EndTime)
					{
						EmpressGreenShellPlugin.RaiseToAll(192, new object[1] { shell.ShellId });
						Object.Destroy((Object)(object)shell.Go);
						_shells.RemoveAt(num2);
						continue;
					}
				}
				else if (shell.HasTarget)
				{
					Vector3 val = shell.Go.transform.position + shell.Dir * value * deltaTime;
					val = Vector3.Lerp(val, shell.TargetPos, 1f - Mathf.Exp(-6f * deltaTime));
					shell.Go.transform.position = val;
				}
				if ((Object)(object)shell.Model != (Object)null)
				{
					shell.Model.Rotate(0f, 900f * deltaTime, 0f, (Space)1);
				}
			}
		}

		private void Simulate(Shell shell, float dt, float speed)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//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_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: 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)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//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_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: 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_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			Transform transform = shell.Go.transform;
			Vector3 val = transform.position;
			Vector3 val2 = shell.Dir;
			float num = speed * dt + 0.55f;
			RaycastHit val3 = default(RaycastHit);
			if (Physics.SphereCast(val, 0.44000003f, val2, ref val3, num, _geometryMask, (QueryTriggerInteraction)1))
			{
				Vector3 val4 = Vector3.Reflect(val2, ((RaycastHit)(ref val3)).normal);
				val4.y = 0f;
				if (((Vector3)(ref val4)).sqrMagnitude < 0.001f)
				{
					val4 = -val2;
				}
				val2 = ((Vector3)(ref val4)).normalized;
				val += ((RaycastHit)(ref val3)).normal * 0.05f;
				TriggerBounceSound(shell);
			}
			val += val2 * speed * dt;
			RaycastHit val5 = default(RaycastHit);
			if (Physics.Raycast(val + Vector3.up * 0.7f, Vector3.down, ref val5, 4f, _geometryMask, (QueryTriggerInteraction)1))
			{
				val.y = ((RaycastHit)(ref val5)).point.y + 0.55f;
			}
			shell.Dir = val2;
			transform.position = val;
		}

		internal void ReceiveShellSpawn(object[] data)
		{
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: 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)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: 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_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			if (data == null || data.Length < 8)
			{
				return;
			}
			Convert.ToInt32(data[0]);
			int num = Convert.ToInt32(data[1]);
			if (!HasShell(num))
			{
				Vector3 val = default(Vector3);
				((Vector3)(ref val))..ctor(Convert.ToSingle(data[2]), Convert.ToSingle(data[3]), Convert.ToSingle(data[4]));
				Vector3 forward = default(Vector3);
				((Vector3)(ref forward))..ctor(Convert.ToSingle(data[5]), Convert.ToSingle(data[6]), Convert.ToSingle(data[7]));
				forward.y = 0f;
				if (((Vector3)(ref forward)).sqrMagnitude < 0.001f)
				{
					forward = Vector3.forward;
				}
				((Vector3)(ref forward)).Normalize();
				RaycastHit val2 = default(RaycastHit);
				if (Physics.Raycast(val + Vector3.up * 0.7f, Vector3.down, ref val2, 6f, _geometryMask, (QueryTriggerInteraction)1))
				{
					val.y = ((RaycastHit)(ref val2)).point.y + 0.55f;
				}
				Shell shell = BuildShell(num, val, forward);
				_shells.Add(shell);
				if (SemiFunc.IsMasterClientOrSingleplayer())
				{
					shell.EndTime = NetworkNow() + (double)EmpressGreenShellPlugin.Settings.Lifetime.Value;
					ConsumeItem(num);
				}
				else
				{
					shell.TargetPos = val;
					shell.HasTarget = true;
				}
			}
		}

		internal void ReceiveShellSync(object[] data)
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			if (data != null && data.Length >= 7 && !SemiFunc.IsMasterClientOrSingleplayer())
			{
				int shellId = Convert.ToInt32(data[0]);
				Shell shell = FindShell(shellId);
				if (shell != null)
				{
					shell.TargetPos = new Vector3(Convert.ToSingle(data[1]), Convert.ToSingle(data[2]), Convert.ToSingle(data[3]));
					shell.Dir = new Vector3(Convert.ToSingle(data[4]), Convert.ToSingle(data[5]), Convert.ToSingle(data[6]));
					shell.HasTarget = true;
				}
			}
		}

		internal void ReceiveShellEnd(object[] data)
		{
			if (data == null || data.Length < 1)
			{
				return;
			}
			int num = Convert.ToInt32(data[0]);
			for (int num2 = _shells.Count - 1; num2 >= 0; num2--)
			{
				if (_shells[num2].ShellId == num)
				{
					if ((Object)(object)_shells[num2].Go != (Object)null)
					{
						Object.Destroy((Object)(object)_shells[num2].Go);
					}
					_shells.RemoveAt(num2);
				}
			}
		}

		private void BroadcastSync(Shell shell)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			Vector3 position = shell.Go.transform.position;
			EmpressGreenShellPlugin.RaiseUnreliable(191, new object[7]
			{
				shell.ShellId,
				position.x,
				position.y,
				position.z,
				shell.Dir.x,
				shell.Dir.y,
				shell.Dir.z
			});
		}

		private void TriggerBounceSound(Shell shell)
		{
			if (shell != null && !(shell.SoundCooldown > 0f))
			{
				shell.SoundCooldown = 0.14f;
				PlaySound(shell);
				EmpressGreenShellPlugin.RaiseOthersUnreliable(193, new object[1] { shell.ShellId });
			}
		}

		internal void ReceiveShellBounce(object[] data)
		{
			if (data != null && data.Length >= 1)
			{
				Shell shell = FindShell(Convert.ToInt32(data[0]));
				if (shell != null)
				{
					PlaySound(shell);
				}
			}
		}

		private void PlaySound(Shell shell)
		{
			if (shell != null && !((Object)(object)shell.Audio == (Object)null) && GreenShellAssets.HasClips)
			{
				AudioClip val = ((Random.value < 0.5f) ? GreenShellAssets.Clip("shell_bounce") : GreenShellAssets.Clip("shell_bounce2"));
				if ((Object)(object)val == (Object)null)
				{
					val = GreenShellAssets.Clip("shell_bounce") ?? GreenShellAssets.Clip("shell_bounce2");
				}
				if (!((Object)(object)val == (Object)null))
				{
					shell.Audio.pitch = Random.Range(0.82f, 0.98f);
					shell.Audio.PlayOneShot(val, EmpressGreenShellPlugin.Settings.HitVolume.Value);
				}
			}
		}

		private Shell BuildShell(int shellId, Vector3 pos, Vector3 dir)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Expected O, but got Unknown
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Expected O, but got Unknown
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Expected O, but got Unknown
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Expected O, but got Unknown
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Expected O, but got Unknown
			//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0205: Unknown result type (might be due to invalid IL or missing references)
			//IL_0206: Unknown result type (might be due to invalid IL or missing references)
			//IL_0224: Unknown result type (might be due to invalid IL or missing references)
			//IL_022e: Expected O, but got Unknown
			GameObject val = new GameObject("Empress Green Shell " + shellId);
			Transform model = null;
			if ((Object)(object)GreenShellAssets.ShellPrefab != (Object)null)
			{
				GameObject val2 = Object.Instantiate<GameObject>(GreenShellAssets.ShellPrefab, val.transform, false);
				((Object)val2).name = "Model";
				GreenShellItemBuilder.ScaleToSize(val2, 0.62f);
				Collider[] componentsInChildren = val2.GetComponentsInChildren<Collider>(true);
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					Object.Destroy((Object)(object)componentsInChildren[i]);
				}
				CenterModel(val2);
				model = val2.transform;
			}
			SphereCollider obj = val.AddComponent<SphereCollider>();
			obj.radius = 0.55f;
			((Collider)obj).isTrigger = true;
			HurtCollider obj2 = val.AddComponent<HurtCollider>();
			float value = EmpressGreenShellPlugin.Settings.PlayerFling.Value;
			float value2 = EmpressGreenShellPlugin.Settings.EnemyFling.Value;
			obj2.playerLogic = true;
			obj2.playerKill = false;
			obj2.playerDamage = 0;
			obj2.playerDamageCooldown = 0.5f;
			obj2.playerHitForce = value;
			obj2.playerTumbleForce = value;
			obj2.playerTumbleTorque = value * 0.6f;
			obj2.playerTumbleTime = 2.5f;
			obj2.playerTumbleTorqueAxis = (TorqueAxis)1;
			obj2.enemyLogic = true;
			obj2.enemyKill = false;
			obj2.enemyStun = true;
			obj2.enemyStunType = (EnemyType)4;
			obj2.enemyStunTime = 2.5f;
			obj2.enemyDamage = 0;
			obj2.enemyDamageCooldown = 0.5f;
			obj2.enemyHitForce = value2;
			obj2.enemyHitTorque = value2 * 0.6f;
			obj2.physLogic = false;
			obj2.onImpactAny = new UnityEvent();
			obj2.onImpactPlayer = new UnityEvent();
			obj2.onImpactEnemy = new UnityEvent();
			obj2.onImpactPhysObject = new UnityEvent();
			AudioSource val3 = val.AddComponent<AudioSource>();
			val3.spatialBlend = 1f;
			val3.minDistance = 1.5f;
			val3.maxDistance = 10f;
			val3.rolloffMode = (AudioRolloffMode)1;
			val3.playOnAwake = false;
			val.transform.position = pos;
			Shell shell = new Shell
			{
				ShellId = shellId,
				Go = val,
				Model = model,
				Dir = dir,
				Audio = val3
			};
			obj2.onImpactAny.AddListener((UnityAction)delegate
			{
				TriggerBounceSound(shell);
			});
			return shell;
		}

		private static void CenterModel(GameObject model)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: 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)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			Bounds bounds = default(Bounds);
			((Bounds)(ref bounds))..ctor(model.transform.position, Vector3.zero);
			bool flag = false;
			Renderer[] componentsInChildren = model.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val in componentsInChildren)
			{
				if (!flag)
				{
					bounds = val.bounds;
					flag = true;
				}
				else
				{
					((Bounds)(ref bounds)).Encapsulate(val.bounds);
				}
			}
			if (flag)
			{
				Transform transform = model.transform;
				transform.position -= ((Bounds)(ref bounds)).center;
			}
		}

		private void ConsumeItem(int itemViewId)
		{
			if (itemViewId <= 0)
			{
				return;
			}
			PhotonView val = PhotonView.Find(itemViewId);
			if (!((Object)(object)val == (Object)null) && !((Object)(object)((Component)val).gameObject == (Object)null))
			{
				string text = GreenShellAccess.InstanceName(((Component)val).gameObject.GetComponent<ItemAttributes>());
				if ((Object)(object)StatsManager.instance != (Object)null && !string.IsNullOrEmpty(text))
				{
					StatsManager.instance.ItemRemove(text);
				}
				if (PhotonNetwork.InRoom)
				{
					PhotonNetwork.Destroy(((Component)val).gameObject);
				}
				else
				{
					Object.Destroy((Object)(object)((Component)val).gameObject);
				}
			}
		}

		private bool HasShell(int shellId)
		{
			return FindShell(shellId) != null;
		}

		private Shell FindShell(int shellId)
		{
			for (int i = 0; i < _shells.Count; i++)
			{
				if (_shells[i].ShellId == shellId)
				{
					return _shells[i];
				}
			}
			return null;
		}

		private static double NetworkNow()
		{
			if (!PhotonNetwork.InRoom)
			{
				return Time.realtimeSinceStartup;
			}
			return PhotonNetwork.Time;
		}
	}
}