Cats.dll

Decompiled 13 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 System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using ExitGames.Client.Photon;
using HarmonyLib;
using Photon.Pun;
using Photon.Realtime;
using REPOLib.Modules;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("0.0.0.0")]
namespace Cats;

public enum Rarity
{
	Common,
	Uncommon,
	Rare,
	Custom
}
public class MaterialVariants : MonoBehaviour
{
	public Material[] variants;

	[HideInInspector]
	public int currentVariant;
}
public class CatRarity : MonoBehaviour
{
	public Rarity rarity;

	public bool museumOnly;

	public bool noDisplayName;

	public string defaultName;
}
public class BananipEffects : MonoBehaviour
{
	public float pitchMultiplier = 1.7f;

	public float pitchOscillation = 0.4f;

	public float pitchOscillationSpeed = 3f;

	public float pupilMultiplier = 3f;

	private static readonly FieldInfo _voiceFetchedField = AccessTools.Field(typeof(PlayerAvatar), "voiceChatFetched");

	private static readonly FieldInfo _voiceChatField = AccessTools.Field(typeof(PlayerAvatar), "voiceChat");

	private void Update()
	{
		PhysGrabObject component = ((Component)this).GetComponent<PhysGrabObject>();
		if ((Object)(object)component == (Object)null)
		{
			return;
		}
		foreach (PhysGrabber item in component.playerGrabbing)
		{
			if ((Object)(object)item == (Object)null || (Object)(object)item.playerAvatar == (Object)null)
			{
				continue;
			}
			PlayerAvatar playerAvatar = item.playerAvatar;
			if (!(_voiceFetchedField == null) && (bool)_voiceFetchedField.GetValue(playerAvatar))
			{
				object? obj = _voiceChatField?.GetValue(playerAvatar);
				PlayerVoiceChat val = (PlayerVoiceChat)((obj is PlayerVoiceChat) ? obj : null);
				if (!((Object)(object)val == (Object)null))
				{
					val.OverridePitch(pitchMultiplier, 0.1f, 0.3f, 0.2f, pitchOscillation, pitchOscillationSpeed);
					val.OverrideHearSelf(0f, 0.2f);
				}
			}
		}
	}
}
public class YarnBallDuctTaped : MonoBehaviour
{
	public GameObject grenadePrefab;

	public int spawnCount = 3;

	public Sound soundExplosion;

	public Sound soundExplosionGlobal;

	private ParticleScriptExplosion particleScriptExplosion;

	private PhotonView photonView;

	private ItemGrenade itemGrenade;

	private string _networkPath;

	private static readonly FieldInfo _activatorField = AccessTools.Field(typeof(ItemGrenade), "activatorPlayerAvatar");

	private static readonly FieldInfo _clientNonKinField = AccessTools.Field(typeof(PhysGrabObject), "clientNonKinematic");

	private static readonly FieldInfo _isSpawnedField = AccessTools.Field(typeof(ItemGrenade), "isSpawnedGrenade");

	private static readonly FieldInfo _tickTimeField = AccessTools.Field(typeof(ItemGrenade), "tickTime");

	private static readonly MethodInfo _setActivatorMethod = AccessTools.Method(typeof(ItemGrenade), "SetActivator", (Type[])null, (Type[])null);

	private static readonly FieldInfo _causingHurtField = AccessTools.Field(typeof(ParticleScriptExplosion), "playerCausingHurtOverride");

	private static readonly FieldInfo _fullRuckusField = AccessTools.Field(typeof(ParticleScriptExplosion), "playerHitFullRuckusOverride");

	private void Start()
	{
		particleScriptExplosion = ((Component)this).GetComponent<ParticleScriptExplosion>();
		photonView = ((Component)this).GetComponent<PhotonView>();
		itemGrenade = ((Component)this).GetComponent<ItemGrenade>();
		foreach (KeyValuePair<string, GameObject> prefab in NetworkPrefabs.Prefabs)
		{
			if ((Object)(object)prefab.Value != (Object)null && ((Object)prefab.Value).name.Contains("Yarn Ball Grenade"))
			{
				_networkPath = prefab.Key;
				break;
			}
		}
	}

	public void Explosion()
	{
		//IL_0080: Unknown result type (might be due to invalid IL or missing references)
		//IL_0085: 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_0209: Unknown result type (might be due to invalid IL or missing references)
		//IL_0234: 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)
		//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
		PlayerAvatar val = (PlayerAvatar)(((Object)(object)itemGrenade != (Object)null) ? /*isinst with value type is only supported in some contexts*/: null);
		int activatorViewId = (((Object)(object)val != (Object)null) ? val.photonView.ViewID : (-1));
		Vector3 val2 = default(Vector3);
		for (int i = 0; i < spawnCount; i++)
		{
			((Vector3)(ref val2))..ctor(Random.Range(-0.3f, 0.3f), 0.2f * (float)i, Random.Range(-0.3f, 0.3f));
			Vector3 val3 = ((Component)this).transform.position + val2;
			GameObject val4 = null;
			if (!SemiFunc.IsMultiplayer())
			{
				if ((Object)(object)grenadePrefab != (Object)null)
				{
					val4 = Object.Instantiate<GameObject>(grenadePrefab, val3, Quaternion.identity);
				}
			}
			else if (SemiFunc.IsMasterClient() && _networkPath != null)
			{
				val4 = PhotonNetwork.Instantiate(_networkPath, val3, Quaternion.identity, (byte)0, (object[])null);
			}
			if ((Object)(object)val4 == (Object)null)
			{
				continue;
			}
			ItemGrenade component = val4.GetComponent<ItemGrenade>();
			if ((Object)(object)component != (Object)null)
			{
				_isSpawnedField?.SetValue(component, true);
				_tickTimeField?.SetValue(component, Random.Range(1.5f, 3f));
				if ((Object)(object)val != (Object)null)
				{
					_setActivatorMethod?.Invoke(component, new object[1] { val });
				}
			}
			((MonoBehaviour)CatsPlugin.Instance).StartCoroutine(ActivateNextFrame(val4, activatorViewId));
		}
		if ((Object)(object)particleScriptExplosion != (Object)null)
		{
			if ((Object)(object)val != (Object)null)
			{
				_causingHurtField?.SetValue(particleScriptExplosion, val);
			}
			_fullRuckusField?.SetValue(particleScriptExplosion, true);
			particleScriptExplosion.Spawn(((Component)this).transform.position, 0.6f, 30, 60, 2f, false, true, 1f);
		}
		soundExplosion.Play(((Component)this).transform.position, 1f, 1f, 1f, 1f);
		soundExplosionGlobal.Play(((Component)this).transform.position, 1f, 1f, 1f, 1f);
	}

	private static IEnumerator ActivateNextFrame(GameObject go, int activatorViewId)
	{
		yield return null;
		if ((Object)(object)go == (Object)null)
		{
			yield break;
		}
		ItemToggle component = go.GetComponent<ItemToggle>();
		if ((Object)(object)component != (Object)null)
		{
			component.ToggleItem(true, activatorViewId);
		}
		yield return null;
		if (!((Object)(object)go == (Object)null))
		{
			PhysGrabObject component2 = go.GetComponent<PhysGrabObject>();
			if ((Object)(object)component2 != (Object)null)
			{
				_clientNonKinField?.SetValue(component2, true);
			}
			Rigidbody component3 = go.GetComponent<Rigidbody>();
			if ((Object)(object)component3 != (Object)null)
			{
				component3.isKinematic = false;
				Vector3 val = Quaternion.Euler((float)Random.Range(-30, 30), (float)Random.Range(-180, 180), 0f) * Vector3.forward;
				component3.velocity = val * Random.Range(4f, 8f);
				component3.angularVelocity = Random.insideUnitSphere * Random.Range(3f, 6f);
			}
		}
	}
}
public class StrungUp : MonoBehaviour
{
	public float slowMultiplier = 0.3f;

	public float slowDuration = 3f;

	public float enemySlowSpeed = 0.5f;

	private ParticleSystem _ps;

	private List<ParticleCollisionEvent> _events = new List<ParticleCollisionEvent>();

	private void Awake()
	{
		_ps = ((Component)this).GetComponent<ParticleSystem>();
	}

	private void OnParticleCollision(GameObject other)
	{
		ParticlePhysicsExtensions.GetCollisionEvents(_ps, other, _events);
		PlayerController componentInParent = other.GetComponentInParent<PlayerController>();
		if ((Object)(object)componentInParent != (Object)null)
		{
			componentInParent.OverrideSpeed(slowMultiplier, slowDuration);
			return;
		}
		EnemyNavMeshAgent val = other.GetComponentInParent<EnemyNavMeshAgent>();
		if ((Object)(object)val == (Object)null)
		{
			EnemyRigidbody componentInParent2 = other.GetComponentInParent<EnemyRigidbody>();
			if ((Object)(object)componentInParent2 != (Object)null && (Object)(object)componentInParent2.enemy != (Object)null)
			{
				val = ((Component)componentInParent2.enemy).GetComponentInChildren<EnemyNavMeshAgent>();
			}
		}
		if ((Object)(object)val != (Object)null)
		{
			val.OverrideAgent(enemySlowSpeed, 8f, slowDuration);
		}
	}
}
public class ScriptYarnString : MonoBehaviour
{
	public ParticleSystem[] particles;

	public Material[] particleMaterials;

	public void Explosion()
	{
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		Material val = null;
		MaterialVariants componentInChildren = ((Component)this).GetComponentInChildren<MaterialVariants>();
		if ((Object)(object)componentInChildren != (Object)null && particleMaterials != null && componentInChildren.currentVariant < particleMaterials.Length)
		{
			val = particleMaterials[componentInChildren.currentVariant];
		}
		ParticleSystem[] array = particles;
		foreach (ParticleSystem val2 in array)
		{
			if (!((Object)(object)val2 == (Object)null))
			{
				((Component)val2).transform.position = ((Component)this).transform.position;
				((Component)val2).transform.SetParent((Transform)null);
				((Component)val2).gameObject.SetActive(true);
				if ((Object)(object)val != (Object)null)
				{
					((Renderer)((Component)val2).GetComponent<ParticleSystemRenderer>()).material = val;
				}
				val2.Stop(true);
				val2.Play();
			}
		}
	}
}
public class BestExtractingDevice : MonoBehaviour
{
	public float healRate = 3f;

	public int healAmount = 5;

	public int batteryDrainPerHeal = 10;

	private static readonly FieldInfo _isTumbling = AccessTools.Field(typeof(PlayerAvatar), "isTumbling");

	private static readonly FieldInfo _tumble = AccessTools.Field(typeof(PlayerAvatar), "tumble");

	private static readonly FieldInfo _tumblePhysGrabObject = AccessTools.Field(typeof(PlayerTumble), "physGrabObject");

	private static readonly FieldInfo _health = AccessTools.Field(typeof(PlayerHealth), "health");

	private static readonly FieldInfo _maxHealth = AccessTools.Field(typeof(PlayerHealth), "maxHealth");

	private ItemBattery itemBattery;

	private PhotonView photonView;

	private Transform inCart;

	private float healTimer;

	private void Start()
	{
		itemBattery = ((Component)this).GetComponent<ItemBattery>();
		photonView = ((Component)this).GetComponent<PhotonView>();
		inCart = ((Component)this).transform.Find("In Cart");
	}

	[PunRPC]
	private void RemoveBatteryBars(int bars)
	{
		if (SemiFunc.IsMasterClientOrSingleplayer())
		{
			itemBattery.RemoveFullBar(bars);
		}
	}

	private void Update()
	{
		//IL_0073: 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_00f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fd: Expected O, but got Unknown
		//IL_0116: Unknown result type (might be due to invalid IL or missing references)
		//IL_011d: Expected O, but got Unknown
		//IL_012e: Unknown result type (might be due to invalid IL or missing references)
		if (!SemiFunc.IsMasterClientOrSingleplayer() || SemiFunc.RunIsShop() || (Object)(object)inCart == (Object)null || (Object)(object)itemBattery == (Object)null || itemBattery.batteryLife <= 0f)
		{
			return;
		}
		healTimer += Time.deltaTime;
		if (healTimer < healRate)
		{
			return;
		}
		healTimer = 0f;
		Bounds val = default(Bounds);
		((Bounds)(ref val))..ctor(inCart.position, inCart.localScale);
		foreach (PlayerAvatar player in GameDirector.instance.PlayerList)
		{
			if (!(bool)_isTumbling.GetValue(player))
			{
				continue;
			}
			int num = (int)_health.GetValue(player.playerHealth);
			int num2 = (int)_maxHealth.GetValue(player.playerHealth);
			if (num >= num2)
			{
				continue;
			}
			PlayerTumble val2 = (PlayerTumble)_tumble.GetValue(player);
			if ((Object)(object)val2 == (Object)null)
			{
				continue;
			}
			PhysGrabObject val3 = (PhysGrabObject)_tumblePhysGrabObject.GetValue(val2);
			if (!((Object)(object)val3 == (Object)null) && ((Bounds)(ref val)).Contains(val3.centerPoint))
			{
				player.playerHealth.HealOther(healAmount, true);
				int num3 = Mathf.Max(1, Mathf.RoundToInt((float)batteryDrainPerHeal / (100f / (float)itemBattery.batteryBars)));
				if (SemiFunc.IsMultiplayer())
				{
					photonView.RPC("RemoveBatteryBars", (RpcTarget)2, new object[1] { num3 });
				}
				else
				{
					itemBattery.RemoveFullBar(num3);
				}
			}
		}
	}
}
[BepInPlugin("eberk30.cats", "Cats", "1.13.2")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class CatsPlugin : BaseUnityPlugin
{
	public static CatsPlugin Instance;

	internal static ManualLogSource Log;

	public static ConfigEntry<bool> ControlledSpawning;

	public static ConfigEntry<int> SpawnCount;

	public static ConfigEntry<int> CommonWeight;

	public static ConfigEntry<int> UncommonWeight;

	public static ConfigEntry<int> RareWeight;

	public static ConfigEntry<int> CustomWeight;

	public static ConfigEntry<float> BananipSpeedMultiplier;

	public static ConfigEntry<float> BananipVignetteIntensity;

	public static ConfigEntry<float> BananipLensDistortionIntensity;

	public static ConfigEntry<float> BananipFovPulseAmount;

	public static ConfigEntry<float> BananipFovPulseSpeed;

	public static ConfigEntry<float> BananipJoltInterval;

	public static ConfigEntry<float> BananipJoltStrength;

	internal static readonly Dictionary<string, ConfigEntry<string>> DisplayNames = new Dictionary<string, ConfigEntry<string>>();

	internal static readonly Dictionary<string, string> DefaultNames = new Dictionary<string, string>();

	internal static readonly HashSet<string> CatPrefabNames = new HashSet<string>();

	private static readonly string[] _displayNameCats = new string[19]
	{
		"Alien Cat", "Black Cat", "Blue Point", "Calico", "Cyberpunk Cat", "Galaxy Cat", "Gray Tabby", "Munchkin", "Orange Tabby", "Pallas Cat",
		"Photosynthesis Cat", "Pink Cat", "Russian Blue", "Scottish Fold", "Siamese", "Sphynx", "Tortoise", "Tuxedo", "White Cat"
	};

	public static NetworkedEvent ShareNamesEvent;

	public static NetworkedEvent AssignNamesEvent;

	public static NetworkedEvent RequestConfigsEvent;

	public static NetworkedEvent AssignVariantsEvent;

	private static readonly Dictionary<int, string> _receivedConfigs = new Dictionary<int, string>();

	internal static readonly Dictionary<int, string> AssignedNames = new Dictionary<int, string>();

	internal static readonly Dictionary<int, int> AssignedVariants = new Dictionary<int, int>();

	private static Dictionary<string, HashSet<int>> _prevLevelVariants = new Dictionary<string, HashSet<int>>();

	private static Dictionary<string, HashSet<int>> _thisLevelVariants = new Dictionary<string, HashSet<int>>();

	private static bool _sentThisLevel = false;

	private static string _lastLevel = "";

	private void Awake()
	{
		//IL_0054: Unknown result type (might be due to invalid IL or missing references)
		//IL_005e: Expected O, but got Unknown
		//IL_0087: Unknown result type (might be due to invalid IL or missing references)
		//IL_0091: Expected O, but got Unknown
		//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c4: Expected O, but got Unknown
		//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f7: Expected O, but got Unknown
		//IL_0120: Unknown result type (might be due to invalid IL or missing references)
		//IL_012a: Expected O, but got Unknown
		//IL_015d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0167: Expected O, but got Unknown
		//IL_019a: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a4: Expected O, but got Unknown
		//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e1: Expected O, but got Unknown
		//IL_0214: Unknown result type (might be due to invalid IL or missing references)
		//IL_021e: Expected O, but got Unknown
		//IL_0251: Unknown result type (might be due to invalid IL or missing references)
		//IL_025b: Expected O, but got Unknown
		//IL_028e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0298: Expected O, but got Unknown
		//IL_02cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d5: Expected O, but got Unknown
		//IL_0334: Unknown result type (might be due to invalid IL or missing references)
		//IL_033e: Expected O, but got Unknown
		//IL_034f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0359: Expected O, but got Unknown
		//IL_036a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0374: Expected O, but got Unknown
		//IL_0385: Unknown result type (might be due to invalid IL or missing references)
		//IL_038f: Expected O, but got Unknown
		//IL_03a4: Unknown result type (might be due to invalid IL or missing references)
		Instance = this;
		Log = ((BaseUnityPlugin)this).Logger;
		ControlledSpawning = ((BaseUnityPlugin)this).Config.Bind<bool>("Controlled Spawning", "Controlled Spawning", false, "Take over spawning. On = Control spawning using count/weight settings below; Off = let the game spawn cats normally.");
		SpawnCount = ((BaseUnityPlugin)this).Config.Bind<int>("Controlled Spawning", "Spawn Count", 3, new ConfigDescription("How many cats appear per level.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 20), Array.Empty<object>()));
		CommonWeight = ((BaseUnityPlugin)this).Config.Bind<int>("Controlled Spawning", "Common Weight", 90, new ConfigDescription("Relative spawn weight for Common rarity cats. Higher = more frequent.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
		UncommonWeight = ((BaseUnityPlugin)this).Config.Bind<int>("Controlled Spawning", "Uncommon Weight", 60, new ConfigDescription("Relative spawn weight for Uncommon rarity cats. Higher = more frequent.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
		RareWeight = ((BaseUnityPlugin)this).Config.Bind<int>("Controlled Spawning", "Rare Weight", 20, new ConfigDescription("Relative spawn weight for Rare rarity cats. Higher = more frequent.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
		CustomWeight = ((BaseUnityPlugin)this).Config.Bind<int>("Controlled Spawning", "Custom Weight", 50, new ConfigDescription("Relative spawn weight for Custom rarity cats. Higher = more frequent.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
		BananipSpeedMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Bananip", "Speed Multiplier", 1.8f, new ConfigDescription("Movement speed multiplier while holding the Bananip.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 5f), Array.Empty<object>()));
		BananipVignetteIntensity = ((BaseUnityPlugin)this).Config.Bind<float>("Bananip", "Vignette Intensity", 0.8f, new ConfigDescription("Peak vignette darkness.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
		BananipLensDistortionIntensity = ((BaseUnityPlugin)this).Config.Bind<float>("Bananip", "Lens Distortion Intensity", 1f, new ConfigDescription("Peak lens distortion amount.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
		BananipFovPulseAmount = ((BaseUnityPlugin)this).Config.Bind<float>("Bananip", "FOV Pulse Amount", 20f, new ConfigDescription("Degrees the FOV pulses up and down.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 30f), Array.Empty<object>()));
		BananipFovPulseSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Bananip", "FOV Pulse Speed", 1.6f, new ConfigDescription("Oscillations per second for FOV and vignette pulse.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 10f), Array.Empty<object>()));
		BananipJoltInterval = ((BaseUnityPlugin)this).Config.Bind<float>("Bananip", "Jolt Interval", 4f, new ConfigDescription("Seconds between random movement jolts.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 30f), Array.Empty<object>()));
		BananipJoltStrength = ((BaseUnityPlugin)this).Config.Bind<float>("Bananip", "Jolt Strength", 15f, new ConfigDescription("Force applied per jolt.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 50f), Array.Empty<object>()));
		string[] displayNameCats = _displayNameCats;
		foreach (string text in displayNameCats)
		{
			DisplayNames[text] = ((BaseUnityPlugin)this).Config.Bind<string>("Cat Names", text, "", "Name shown when holding " + text + ". Comma-separate for random pick: Bob, Bill. Leave blank for no name.");
		}
		ShareNamesEvent = new NetworkedEvent("ShareNames", (Action<EventData>)OnShareNames);
		AssignNamesEvent = new NetworkedEvent("AssignNames", (Action<EventData>)OnAssignNames);
		RequestConfigsEvent = new NetworkedEvent("RequestConfigs", (Action<EventData>)OnRequestConfigs);
		AssignVariantsEvent = new NetworkedEvent("AssignVariants", (Action<EventData>)OnAssignVariants);
		((MonoBehaviour)Instance).StartCoroutine(BakeWhenReady());
		new Harmony("eberk30.cats").PatchAll();
	}

	private static IEnumerator BakeWhenReady()
	{
		while (Valuables.RegisteredValuables.Count == 0)
		{
			yield return (object)new WaitForSeconds(0.5f);
		}
		BakeItemAttributesIntoCatPrefabs();
	}

	internal static void BakeItemAttributesIntoCatPrefabs()
	{
		//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f1: Expected O, but got Unknown
		bool flag = Chainloader.PluginInfos.ContainsKey("eberk30.genesis");
		foreach (PrefabRef registeredValuable in Valuables.RegisteredValuables)
		{
			if (!NetworkPrefabs.Prefabs.TryGetValue(((PrefabRef<GameObject>)(object)registeredValuable).ResourcePath, out var value) || (Object)(object)value == (Object)null)
			{
				continue;
			}
			CatRarity component = value.GetComponent<CatRarity>();
			if ((Object)(object)component == (Object)null || (flag && ((PrefabRef<GameObject>)(object)registeredValuable).PrefabName == "Genesis") || !CatPrefabNames.Add(((PrefabRef<GameObject>)(object)registeredValuable).PrefabName))
			{
				continue;
			}
			if ((Object)(object)value.GetComponent<ItemAttributes>() == (Object)null)
			{
				value.AddComponent<ItemAttributes>();
			}
			if (!component.noDisplayName)
			{
				if (!string.IsNullOrEmpty(component.defaultName))
				{
					DefaultNames[((PrefabRef<GameObject>)(object)registeredValuable).PrefabName] = component.defaultName;
					((BaseUnityPlugin)Instance).Config.Remove(new ConfigDefinition("Cat Names", ((PrefabRef<GameObject>)(object)registeredValuable).PrefabName));
					DisplayNames.Remove(((PrefabRef<GameObject>)(object)registeredValuable).PrefabName);
				}
				else
				{
					DisplayNames[((PrefabRef<GameObject>)(object)registeredValuable).PrefabName] = ((BaseUnityPlugin)Instance).Config.Bind<string>("Cat Names", ((PrefabRef<GameObject>)(object)registeredValuable).PrefabName, "", "Name shown when holding " + ((PrefabRef<GameObject>)(object)registeredValuable).PrefabName + ". Comma-separate for random pick: Bob, Bill. Leave blank for no name.");
				}
			}
			Log.LogDebug((object)$"[Cats] baked {((PrefabRef<GameObject>)(object)registeredValuable).PrefabName} rarity={component.rarity}");
		}
	}

	internal static string GetCatType(string name)
	{
		foreach (string catPrefabName in CatPrefabNames)
		{
			if (name.Contains(catPrefabName))
			{
				return catPrefabName;
			}
		}
		return null;
	}

	internal static bool IsCat(string name)
	{
		return GetCatType(name) != null;
	}

	internal static int PickVariant(string typeKey, int count)
	{
		HashSet<int> exclude = new HashSet<int>();
		if (_prevLevelVariants.TryGetValue(typeKey, out var value))
		{
			exclude.UnionWith(value);
		}
		if (_thisLevelVariants.TryGetValue(typeKey, out var value2))
		{
			exclude.UnionWith(value2);
		}
		int[] array = ((exclude.Count >= count) ? Enumerable.Range(0, count).ToArray() : (from i in Enumerable.Range(0, count)
			where !exclude.Contains(i)
			select i).ToArray());
		int num = array[Random.Range(0, array.Length)];
		if (!_thisLevelVariants.TryGetValue(typeKey, out var value3))
		{
			value3 = (_thisLevelVariants[typeKey] = new HashSet<int>());
		}
		value3.Add(num);
		return num;
	}

	private static void OnShareNames(EventData photonEvent)
	{
		if (photonEvent.CustomData is string text)
		{
			_receivedConfigs[photonEvent.Sender] = text;
			Log.LogDebug((object)$"[Cats] got config from actor {photonEvent.Sender} ({text.Length} bytes)");
		}
	}

	private static void OnRequestConfigs(EventData photonEvent)
	{
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		Log.LogDebug((object)$"[Cats] received config request (isMaster={SemiFunc.IsMasterClientOrSingleplayer()})");
		if (!SemiFunc.IsMasterClientOrSingleplayer())
		{
			ShareNamesEvent.RaiseEvent((object)PackConfig(), NetworkingEvents.RaiseMasterClient, SendOptions.SendReliable);
			Log.LogDebug((object)"[Cats] replied with config");
		}
	}

	private static void OnAssignNames(EventData photonEvent)
	{
		if (!(photonEvent.CustomData is string text))
		{
			return;
		}
		string[] array = text.Split(new char[1] { '|' });
		foreach (string text2 in array)
		{
			int num = text2.IndexOf('=');
			if (num >= 0)
			{
				if (!int.TryParse(text2.Substring(0, num), out var result))
				{
					Log.LogWarning((object)("[Cats] couldn't parse viewID: " + text2));
				}
				else
				{
					AssignedNames[result] = text2.Substring(num + 1);
				}
			}
		}
		ValuableObject[] array2 = Object.FindObjectsOfType<ValuableObject>();
		foreach (ValuableObject val in array2)
		{
			PhotonView component = ((Component)val).GetComponent<PhotonView>();
			if (!((Object)(object)component == (Object)null) && AssignedNames.TryGetValue(component.ViewID, out var value))
			{
				ItemAttributes component2 = ((Component)val).GetComponent<ItemAttributes>();
				if ((Object)(object)component2 != (Object)null && (Object)(object)component2.item != (Object)null)
				{
					component2.item.itemName = value;
				}
			}
		}
	}

	private static void OnAssignVariants(EventData photonEvent)
	{
		if (!(photonEvent.CustomData is string text))
		{
			return;
		}
		string[] array = text.Split(new char[1] { '|' });
		foreach (string text2 in array)
		{
			int num = text2.IndexOf('=');
			if (num >= 0 && int.TryParse(text2.Substring(0, num), out var result) && int.TryParse(text2.Substring(num + 1), out var result2))
			{
				AssignedVariants[result] = result2;
			}
		}
		ItemAttributes[] array2 = Object.FindObjectsOfType<ItemAttributes>();
		foreach (ItemAttributes val in array2)
		{
			MaterialVariants componentInChildren = ((Component)val).GetComponentInChildren<MaterialVariants>();
			if ((Object)(object)componentInChildren == (Object)null)
			{
				continue;
			}
			PhotonView component = ((Component)val).GetComponent<PhotonView>();
			if ((Object)(object)component == (Object)null || !AssignedVariants.TryGetValue(component.ViewID, out var value) || componentInChildren.variants == null || value >= componentInChildren.variants.Length)
			{
				continue;
			}
			MeshRenderer[] componentsInChildren = ((Component)val).GetComponentsInChildren<MeshRenderer>();
			if (componentsInChildren.Length == 0)
			{
				continue;
			}
			MeshRenderer[] array3 = componentsInChildren;
			for (int j = 0; j < array3.Length; j++)
			{
				((Renderer)array3[j]).material = componentInChildren.variants[value];
			}
			if (componentInChildren.variants[value].HasProperty("_FresnelScale"))
			{
				continue;
			}
			ItemLight[] componentsInChildren2 = ((Component)val).GetComponentsInChildren<ItemLight>();
			foreach (ItemLight val2 in componentsInChildren2)
			{
				array3 = componentsInChildren;
				foreach (MeshRenderer item in array3)
				{
					val2.meshRenderers.Remove(item);
				}
			}
		}
	}

	private static string PackConfig()
	{
		return string.Join("|", DisplayNames.Select((KeyValuePair<string, ConfigEntry<string>> kvp) => kvp.Key + "=" + kvp.Value.Value));
	}

	internal static void TrySendConfig()
	{
		//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
		RunManager instance = RunManager.instance;
		object obj;
		if (instance == null)
		{
			obj = null;
		}
		else
		{
			Level levelCurrent = instance.levelCurrent;
			obj = ((levelCurrent != null) ? ((Object)levelCurrent).name : null);
		}
		if (obj == null)
		{
			obj = "";
		}
		Room currentRoom = PhotonNetwork.CurrentRoom;
		string text = (string?)obj + "|" + ((currentRoom != null) ? currentRoom.Name : null);
		if (text != _lastLevel)
		{
			_lastLevel = text;
			_sentThisLevel = false;
			AssignedNames.Clear();
			AssignedVariants.Clear();
			if (SemiFunc.IsMasterClientOrSingleplayer())
			{
				_receivedConfigs.Clear();
				_prevLevelVariants = _thisLevelVariants;
				_thisLevelVariants = new Dictionary<string, HashSet<int>>();
			}
		}
		if (!_sentThisLevel && PhotonNetwork.InRoom)
		{
			_sentThisLevel = true;
			if (SemiFunc.IsMasterClientOrSingleplayer())
			{
				_receivedConfigs[PhotonNetwork.LocalPlayer.ActorNumber] = PackConfig();
				Log.LogDebug((object)"[Cats] host stored own config");
			}
			else
			{
				ShareNamesEvent.RaiseEvent((object)PackConfig(), NetworkingEvents.RaiseMasterClient, SendOptions.SendReliable);
				Log.LogDebug((object)"[Cats] client sent config to master");
			}
		}
	}

	private static List<string> GetNames(string serialized, string catType)
	{
		List<string> list = new List<string>();
		string text = catType + "=";
		string[] array = serialized.Split(new char[1] { '|' });
		foreach (string text2 in array)
		{
			if (!text2.StartsWith(text))
			{
				continue;
			}
			string[] array2 = text2.Substring(text.Length).Split(new char[1] { ',' });
			for (int j = 0; j < array2.Length; j++)
			{
				string text3 = array2[j].Trim();
				if (text3.Length > 0)
				{
					list.Add(text3);
				}
			}
			break;
		}
		return list;
	}

	internal IEnumerator AssignCatNames()
	{
		yield return null;
		int num = PhotonNetwork.PlayerList.Length - 1;
		Log.LogDebug((object)$"[Cats] requesting configs from {num} other player(s)");
		RequestConfigsEvent.RaiseEvent((object)"", NetworkingEvents.RaiseOthers, SendOptions.SendReliable);
		float waited = 0f;
		int expected = PhotonNetwork.PlayerList.Length;
		while (_receivedConfigs.Count < expected && waited < 8f)
		{
			yield return null;
			waited += Time.deltaTime;
		}
		if (waited >= 8f)
		{
			Log.LogWarning((object)$"[Cats] timed out waiting for name configs ({_receivedConfigs.Count}/{expected})");
		}
		StringBuilder stringBuilder = new StringBuilder();
		ValuableObject[] array = Object.FindObjectsOfType<ValuableObject>();
		foreach (ValuableObject val in array)
		{
			string catType = GetCatType(((Object)((Component)val).gameObject).name);
			if (catType == null)
			{
				continue;
			}
			PhotonView component = ((Component)val).GetComponent<PhotonView>();
			if ((Object)(object)component == (Object)null)
			{
				continue;
			}
			List<string> list = new List<string>();
			foreach (string value2 in _receivedConfigs.Values)
			{
				list.AddRange(GetNames(value2, catType));
			}
			if (list.Count != 0)
			{
				string value = list[Random.Range(0, list.Count)];
				AssignedNames[component.ViewID] = value;
				if (stringBuilder.Length > 0)
				{
					stringBuilder.Append('|');
				}
				stringBuilder.Append(component.ViewID).Append('=').Append(value);
			}
		}
		if (stringBuilder.Length > 0)
		{
			AssignNamesEvent.RaiseEvent((object)stringBuilder.ToString(), NetworkingEvents.RaiseAll, SendOptions.SendReliable);
		}
	}
}
[HarmonyPatch(typeof(ValuableObject), "Start")]
internal static class AttributesPatch
{
	[HarmonyPostfix]
	private static void Postfix(ValuableObject __instance)
	{
		if (CatsPlugin.IsCat(((Object)((Component)__instance).gameObject).name) && !((Object)(object)((Component)__instance).gameObject.GetComponent<ItemAttributes>() != (Object)null))
		{
			((Component)__instance).gameObject.AddComponent<ItemAttributes>();
		}
	}
}
[HarmonyPatch(typeof(ItemAttributes), "Awake")]
internal static class AwakePatch
{
	[HarmonyPostfix]
	private static void Postfix(ItemAttributes __instance)
	{
		//IL_0265: Unknown result type (might be due to invalid IL or missing references)
		if (CatsPlugin.CatPrefabNames.Count == 0)
		{
			CatsPlugin.BakeItemAttributesIntoCatPrefabs();
		}
		string catType = CatsPlugin.GetCatType(((Object)((Component)__instance).gameObject).name);
		if (catType != null)
		{
			CatsPlugin.TrySendConfig();
			if ((Object)(object)__instance.item == (Object)null)
			{
				__instance.item = ScriptableObject.CreateInstance<Item>();
				__instance.item.value = ScriptableObject.CreateInstance<Value>();
			}
			PhotonView component = ((Component)__instance).GetComponent<PhotonView>();
			string value2;
			if ((Object)(object)component != (Object)null && CatsPlugin.AssignedNames.TryGetValue(component.ViewID, out var value))
			{
				__instance.item.itemName = value;
			}
			else if (CatsPlugin.DefaultNames.TryGetValue(catType, out value2))
			{
				__instance.item.itemName = value2;
			}
			else
			{
				ConfigEntry<string> value3;
				string[] array = (from s in (CatsPlugin.DisplayNames.TryGetValue(catType, out value3) ? value3.Value : "").Split(new char[1] { ',' })
					select s.Trim() into s
					where s.Length > 0
					select s).ToArray();
				__instance.item.itemName = ((array.Length != 0) ? array[Random.Range(0, array.Length)] : "");
			}
		}
		PhotonView component2 = ((Component)__instance).GetComponent<PhotonView>();
		if ((Object)(object)component2 == (Object)null)
		{
			return;
		}
		MaterialVariants componentInChildren = ((Component)__instance).GetComponentInChildren<MaterialVariants>();
		if ((Object)(object)componentInChildren == (Object)null || componentInChildren.variants == null || componentInChildren.variants.Length == 0)
		{
			return;
		}
		MeshRenderer[] componentsInChildren = ((Component)__instance).GetComponentsInChildren<MeshRenderer>();
		if (componentsInChildren.Length == 0)
		{
			return;
		}
		bool flag = false;
		if (CatsPlugin.AssignedVariants.TryGetValue(component2.ViewID, out var value4))
		{
			MeshRenderer[] array2 = componentsInChildren;
			for (int num = 0; num < array2.Length; num++)
			{
				((Renderer)array2[num]).material = componentInChildren.variants[value4];
			}
			flag = true;
		}
		else if (SemiFunc.IsMasterClientOrSingleplayer())
		{
			value4 = CatsPlugin.PickVariant(catType ?? ((Object)((Component)__instance).gameObject).name, componentInChildren.variants.Length);
			CatsPlugin.AssignedVariants[component2.ViewID] = value4;
			MeshRenderer[] array2 = componentsInChildren;
			for (int num = 0; num < array2.Length; num++)
			{
				((Renderer)array2[num]).material = componentInChildren.variants[value4];
			}
			CatsPlugin.AssignVariantsEvent.RaiseEvent((object)(component2.ViewID + "=" + value4), NetworkingEvents.RaiseOthers, SendOptions.SendReliable);
			flag = true;
		}
		if (flag)
		{
			componentInChildren.currentVariant = value4;
			string text = ((Object)((Component)__instance).gameObject).name.Replace("(Clone)", "").ToLowerInvariant();
			string path = Path.Combine(Application.persistentDataPath, "Cache", "Icons", "Items", text + ".png");
			if (File.Exists(path))
			{
				File.Delete(path);
			}
		}
	}
}
[HarmonyPatch(typeof(ItemAttributes), "Start")]
internal static class StartPatch
{
	[HarmonyPrefix]
	private static void Prefix(ItemAttributes __instance)
	{
		if (CatsPlugin.GetCatType(((Object)((Component)__instance).gameObject).name) != null)
		{
			CatsPlugin.TrySendConfig();
			if (!((Object)(object)__instance.item != (Object)null))
			{
				Item val = ScriptableObject.CreateInstance<Item>();
				val.value = ScriptableObject.CreateInstance<Value>();
				val.itemName = "";
				__instance.item = val;
			}
		}
	}

	[HarmonyPostfix]
	private static void Postfix(ItemAttributes __instance)
	{
		if (CatsPlugin.GetCatType(((Object)((Component)__instance).gameObject).name) != null)
		{
			ItemManager instance = ItemManager.instance;
			if ((Object)(object)instance != (Object)null)
			{
				instance.spawnedItems.Remove(__instance);
			}
		}
	}
}
[HarmonyPatch(typeof(BatteryVisualLogic), "BatteryBarsSet")]
internal static class BatteryBarsPatch
{
	[HarmonyPrefix]
	private static bool Prefix(BatteryVisualLogic __instance)
	{
		if ((Object)(object)__instance.batteryBarPrefab != (Object)null)
		{
			return true;
		}
		BatteryVisualLogic[] array = Object.FindObjectsOfType<BatteryVisualLogic>();
		foreach (BatteryVisualLogic val in array)
		{
			if ((Object)(object)val != (Object)(object)__instance && (Object)(object)val.batteryBarPrefab != (Object)null)
			{
				__instance.batteryBarPrefab = val.batteryBarPrefab;
				return true;
			}
		}
		return false;
	}
}
[HarmonyPatch(typeof(ItemBattery), "BatteryChargeStartRPC")]
internal static class ItemBatteryChargePatch
{
	private static readonly FieldInfo _bvl = AccessTools.Field(typeof(ItemBattery), "batteryVisualLogic");

	private static readonly FieldInfo _isCharging = AccessTools.Field(typeof(ItemBattery), "isCharging");

	[HarmonyPostfix]
	private static void Postfix(ItemBattery __instance)
	{
		if (_bvl.GetValue(__instance) == null)
		{
			_isCharging.SetValue(__instance, false);
		}
	}
}
[HarmonyPatch(typeof(ItemAttributes), "ShowingInfo")]
internal static class CatNamePatch
{
	private static readonly FieldInfo _promptName = AccessTools.Field(typeof(ItemAttributes), "promptName");

	[HarmonyPostfix]
	private static void Postfix(ItemAttributes __instance)
	{
		if ((Object)(object)__instance.item == (Object)null)
		{
			return;
		}
		string name = ((Object)((Component)__instance).gameObject).name;
		foreach (string catPrefabName in CatsPlugin.CatPrefabNames)
		{
			if (name.Contains(catPrefabName))
			{
				_promptName.SetValue(__instance, __instance.item.itemName);
				break;
			}
		}
	}
}
[HarmonyPatch(typeof(ItemToggle), "ToggleItemLogic")]
internal static class SoundPatch
{
	[HarmonyPostfix]
	private static void Postfix(ItemToggle __instance, bool toggle)
	{
		if (!toggle || !CatsPlugin.IsCat(((Object)((Component)__instance).gameObject).name))
		{
			return;
		}
		PhysGrabObject component = ((Component)__instance).GetComponent<PhysGrabObject>();
		if (!((Object)(object)component == (Object)null) && component.grabbedLocal)
		{
			AudioSource component2 = ((Component)__instance).GetComponent<AudioSource>();
			if ((Object)(object)component2 != (Object)null)
			{
				component2.Play();
			}
		}
	}
}
[HarmonyPatch(typeof(PlayerController), "Update")]
internal static class BananipPatch
{
	private static readonly FieldInfo _grabbedField = AccessTools.Field(typeof(PhysGrabber), "grabbedPhysGrabObject");

	private static readonly FieldInfo _vigActiveField = AccessTools.Field(typeof(PostProcessing), "vignetteOverrideActive");

	private static readonly FieldInfo _vigTimerField = AccessTools.Field(typeof(PostProcessing), "vignetteOverrideTimer");

	private static readonly FieldInfo _vigColorField = AccessTools.Field(typeof(PostProcessing), "vignetteOverrideColor");

	private static readonly FieldInfo _vigIntensityField = AccessTools.Field(typeof(PostProcessing), "vignetteOverrideIntensity");

	private static readonly FieldInfo _vigSmoothnessField = AccessTools.Field(typeof(PostProcessing), "vignetteOverrideSmoothness");

	private static readonly FieldInfo _vigLerpField = AccessTools.Field(typeof(PostProcessing), "vignetteOverrideLerp");

	private static readonly FieldInfo _vigSpeedInField = AccessTools.Field(typeof(PostProcessing), "vignetteOverrideSpeedIn");

	private static readonly FieldInfo _vigSpeedOutField = AccessTools.Field(typeof(PostProcessing), "vignetteOverrideSpeedOut");

	private static readonly FieldInfo _joltImpulseField = AccessTools.Field(typeof(PlayerController), "VelocityImpulse");

	internal static BananipEffects ActiveFx;

	private static float _baseFov;

	private static float _joltTimer;

	[HarmonyPostfix]
	private static void Postfix(PlayerController __instance)
	{
		//IL_033d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0342: Unknown result type (might be due to invalid IL or missing references)
		//IL_0346: Unknown result type (might be due to invalid IL or missing references)
		//IL_034b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0353: Unknown result type (might be due to invalid IL or missing references)
		//IL_035f: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)__instance != (Object)(object)PlayerController.instance)
		{
			return;
		}
		PlayerAvatar playerAvatarScript = __instance.playerAvatarScript;
		BananipEffects bananipEffects = null;
		if ((Object)(object)playerAvatarScript != (Object)null && (Object)(object)playerAvatarScript.physGrabber != (Object)null)
		{
			object? obj = _grabbedField?.GetValue(playerAvatarScript.physGrabber);
			PhysGrabObject val = (PhysGrabObject)((obj is PhysGrabObject) ? obj : null);
			if ((Object)(object)val != (Object)null)
			{
				bananipEffects = ((Component)val).GetComponent<BananipEffects>();
			}
		}
		BananipEffects activeFx = ActiveFx;
		ActiveFx = bananipEffects;
		PostProcessing instance = PostProcessing.Instance;
		if ((Object)(object)bananipEffects == (Object)null)
		{
			if ((Object)(object)instance != (Object)null)
			{
				_vigActiveField?.SetValue(instance, false);
			}
			if (_baseFov > 0f)
			{
				Camera main = Camera.main;
				if ((Object)(object)main != (Object)null)
				{
					main.fieldOfView = _baseFov;
				}
				_baseFov = 0f;
			}
			return;
		}
		if ((Object)(object)activeFx == (Object)null)
		{
			Camera main2 = Camera.main;
			_baseFov = ((main2 != null) ? main2.fieldOfView : 60f);
			_joltTimer = CatsPlugin.BananipJoltInterval.Value;
			if ((Object)(object)instance != (Object)null)
			{
				_vigLerpField?.SetValue(instance, 0f);
			}
		}
		__instance.OverrideSpeed(CatsPlugin.BananipSpeedMultiplier.Value, 0.2f);
		playerAvatarScript.OverridePupilSize(bananipEffects.pupilMultiplier, 3, 15f, 0.3f, 4f, 0.6f, 0.2f);
		if ((Object)(object)instance != (Object)null)
		{
			_vigActiveField?.SetValue(instance, true);
			_vigTimerField?.SetValue(instance, 0.2f);
			_vigColorField?.SetValue(instance, Color.black);
			float num = (Mathf.Sin(Time.time * CatsPlugin.BananipFovPulseSpeed.Value) + 1f) * 0.5f;
			float value = CatsPlugin.BananipVignetteIntensity.Value;
			_vigIntensityField?.SetValue(instance, Mathf.Lerp(value * 0.3f, value, num));
			_vigSmoothnessField?.SetValue(instance, 0.8f);
			_vigSpeedInField?.SetValue(instance, 1.5f);
			_vigSpeedOutField?.SetValue(instance, 2f);
			float num2 = Mathf.Abs(Mathf.Sin(Time.time * 2f)) * CatsPlugin.BananipLensDistortionIntensity.Value;
			instance.LensDistortionOverride(num2, 8f, 4f, 0.2f, (GameObject)null);
		}
		Camera main3 = Camera.main;
		if ((Object)(object)main3 != (Object)null && _baseFov > 0f)
		{
			main3.fieldOfView = _baseFov + Mathf.Sin(Time.time * CatsPlugin.BananipFovPulseSpeed.Value) * CatsPlugin.BananipFovPulseAmount.Value;
		}
		_joltTimer -= Time.deltaTime;
		if (_joltTimer <= 0f)
		{
			_joltTimer = CatsPlugin.BananipJoltInterval.Value;
			if (_joltImpulseField != null)
			{
				Vector3 val2 = new Vector3(Random.Range(-1f, 1f), 0f, Random.Range(-1f, 1f));
				Vector3 normalized = ((Vector3)(ref val2)).normalized;
				_joltImpulseField.SetValue(__instance, normalized * CatsPlugin.BananipJoltStrength.Value);
			}
		}
	}
}
[HarmonyPatch(typeof(ValuableDirector), "SetupHost")]
internal static class SpawnPatch
{
	private static readonly Dictionary<Type, Vector3> _volSizes = new Dictionary<Type, Vector3>
	{
		{
			(Type)0,
			new Vector3(0.25f, 0.25f, 0.25f)
		},
		{
			(Type)1,
			new Vector3(0.5f, 0.5f, 0.5f)
		},
		{
			(Type)2,
			new Vector3(0.826f, 1f, 0.826f)
		},
		{
			(Type)3,
			new Vector3(1.25f, 1.5f, 1.25f)
		},
		{
			(Type)4,
			new Vector3(3f, 2.4f, 1.2f)
		},
		{
			(Type)5,
			new Vector3(2.4f, 3f, 1.2f)
		},
		{
			(Type)6,
			new Vector3(1.25f, 3.5f, 1.25f)
		}
	};

	[HarmonyPostfix]
	private static void Postfix(ValuableDirector __instance)
	{
		try
		{
			PostfixBody(__instance);
		}
		catch (Exception arg)
		{
			CatsPlugin.Log.LogError((object)$"[Cats] SpawnPatch failed: {arg}");
		}
	}

	private static void PostfixBody(ValuableDirector __instance)
	{
		//IL_0085: 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_00b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c3: 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)
		if (!SemiFunc.IsMasterClientOrSingleplayer())
		{
			return;
		}
		RunManager instance = RunManager.instance;
		Level levelCurrent = instance.levelCurrent;
		if ((Object)(object)levelCurrent == (Object)(object)instance.levelMainMenu || (Object)(object)levelCurrent == (Object)(object)instance.levelLobbyMenu || (Object)(object)levelCurrent == (Object)(object)instance.levelLobby || !PhotonNetwork.InRoom)
		{
			return;
		}
		CatsPlugin.TrySendConfig();
		if (!CatsPlugin.ControlledSpawning.Value)
		{
			((MonoBehaviour)__instance).StartCoroutine(CatsPlugin.Instance.AssignCatNames());
			return;
		}
		Dictionary<Type, List<Tuple<Vector3, Quaternion>>> dictionary = new Dictionary<Type, List<Tuple<Vector3, Quaternion>>>();
		ValuableVolume[] array = Object.FindObjectsOfType<ValuableVolume>();
		foreach (ValuableVolume val in array)
		{
			if (!dictionary.ContainsKey(val.VolumeType))
			{
				dictionary[val.VolumeType] = new List<Tuple<Vector3, Quaternion>>();
			}
			dictionary[val.VolumeType].Add(Tuple.Create<Vector3, Quaternion>(((Component)val).transform.position, ((Component)val).transform.rotation));
		}
		CatsPlugin.Log.LogDebug((object)$"[Cats] captured {dictionary.Values.Sum((List<Tuple<Vector3, Quaternion>> l) => l.Count)} volumes across {dictionary.Count} types");
		((MonoBehaviour)__instance).StartCoroutine(SpawnCats(__instance, dictionary));
	}

	private static IEnumerator SpawnCats(ValuableDirector director, Dictionary<Type, List<Tuple<Vector3, Quaternion>>> volumesByType)
	{
		CatsPlugin.Log.LogDebug((object)"[Cats] SpawnCats coroutine started");
		if (CatsPlugin.CatPrefabNames.Count == 0)
		{
			CatsPlugin.BakeItemAttributesIntoCatPrefabs();
		}
		int prev = -1;
		int stable = 0;
		float waited = 0f;
		while (stable < 3 || waited < 1f)
		{
			yield return (object)new WaitForSeconds(0.2f);
			waited += 0.2f;
			int num = Object.FindObjectsOfType<ValuableObject>().Length;
			if (num == prev)
			{
				stable++;
				continue;
			}
			stable = 0;
			prev = num;
		}
		CatsPlugin.Log.LogDebug((object)$"[Cats] stability check done — {prev} valuables in scene");
		bool isMuseum = ((Object)RunManager.instance.levelCurrent).name == "Level - Museum";
		List<PrefabRef> pool = Valuables.RegisteredValuables.Where((PrefabRef v) => CatsPlugin.CatPrefabNames.Contains(((PrefabRef<GameObject>)(object)v).PrefabName) && (isMuseum || (Object)(object)((PrefabRef<GameObject>)(object)v).Prefab == (Object)null || !((PrefabRef<GameObject>)(object)v).Prefab.GetComponent<CatRarity>().museumOnly)).ToList();
		if (pool.Count == 0)
		{
			CatsPlugin.Log.LogWarning((object)"[Cats] cat pool is empty, nothing to spawn");
			yield break;
		}
		ValuableObject[] array = Object.FindObjectsOfType<ValuableObject>();
		int num2 = 0;
		ValuableObject[] array2 = array;
		foreach (ValuableObject val in array2)
		{
			if (CatsPlugin.IsCat(((Object)((Component)val).gameObject).name))
			{
				PhotonNetwork.Destroy(((Component)val).gameObject);
				num2++;
			}
		}
		if (num2 > 0)
		{
			CatsPlugin.Log.LogDebug((object)$"[Cats] removed {num2} naturally spawned cats");
			yield return (object)new WaitForSeconds(0.1f);
			array = Object.FindObjectsOfType<ValuableObject>();
		}
		List<Vector3> occupied = new List<Vector3>();
		array2 = array;
		foreach (ValuableObject val2 in array2)
		{
			occupied.Add(((Component)val2).transform.position);
		}
		foreach (List<Tuple<Vector3, Quaternion>> value6 in volumesByType.Values)
		{
			value6.RemoveAll(delegate(Tuple<Vector3, Quaternion> v)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_0012: Unknown result type (might be due to invalid IL or missing references)
				//IL_0017: 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_001d: Unknown result type (might be due to invalid IL or missing references)
				Vector3 item = v.Item1;
				for (int i = 0; i < occupied.Count; i++)
				{
					Vector3 val5 = occupied[i] - item;
					if (((Vector3)(ref val5)).sqrMagnitude < 1f)
					{
						return true;
					}
				}
				return false;
			});
		}
		int geoMask = LayerMask.GetMask(new string[1] { "Default" });
		int geoSkipped = 0;
		foreach (KeyValuePair<Type, List<Tuple<Vector3, Quaternion>>> item2 in volumesByType)
		{
			Vector3 s = _volSizes[item2.Key];
			item2.Value.RemoveAll(delegate(Tuple<Vector3, Quaternion> v)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0007: Unknown result type (might be due to invalid IL or missing references)
				//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_0027: 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_0032: Unknown result type (might be due to invalid IL or missing references)
				//IL_0037: Unknown result type (might be due to invalid IL or missing references)
				//IL_003c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0052: Unknown result type (might be due to invalid IL or missing references)
				//IL_0057: Unknown result type (might be due to invalid IL or missing references)
				//IL_005c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0066: 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_0071: Unknown result type (might be due to invalid IL or missing references)
				//IL_007b: 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)
				if (Physics.OverlapBox(v.Item1 + v.Item2 * Vector3.forward * (s.z / 2f) + v.Item2 * Vector3.up * (s.y / 2f) + Vector3.up * 0.01f, s / 2f, v.Item2, geoMask, (QueryTriggerInteraction)1).Length != 0)
				{
					int num9 = geoSkipped;
					geoSkipped = num9 + 1;
					return true;
				}
				return false;
			});
		}
		if (geoSkipped > 0)
		{
			CatsPlugin.Log.LogDebug((object)$"[Cats] {geoSkipped} volumes blocked by geometry");
		}
		int num4 = CatsPlugin.CommonWeight.Value + CatsPlugin.UncommonWeight.Value + CatsPlugin.RareWeight.Value + CatsPlugin.CustomWeight.Value;
		if (num4 <= 0)
		{
			CatsPlugin.Log.LogWarning((object)"[Cats] all weights are 0, nothing to spawn");
			yield break;
		}
		List<PrefabRef> list = new List<PrefabRef>();
		List<PrefabRef> list2 = new List<PrefabRef>();
		List<PrefabRef> list3 = new List<PrefabRef>();
		List<PrefabRef> list4 = new List<PrefabRef>();
		foreach (PrefabRef item3 in pool)
		{
			switch (((PrefabRef<GameObject>)(object)item3).Prefab.GetComponent<CatRarity>().rarity)
			{
			case Rarity.Common:
				list.Add(item3);
				break;
			case Rarity.Uncommon:
				list2.Add(item3);
				break;
			case Rarity.Rare:
				list3.Add(item3);
				break;
			case Rarity.Custom:
				list4.Add(item3);
				break;
			}
		}
		int value = CatsPlugin.SpawnCount.Value;
		int num5 = 0;
		int num6 = 0;
		while (num5 < value && num6 < 60)
		{
			num6++;
			int num7 = Random.Range(0, num4);
			int value2 = CatsPlugin.CommonWeight.Value;
			int value3 = CatsPlugin.UncommonWeight.Value;
			int value4 = CatsPlugin.RareWeight.Value;
			Rarity rarity = ((num7 >= value2) ? ((num7 < value2 + value3) ? Rarity.Uncommon : ((num7 >= value2 + value3 + value4) ? Rarity.Custom : Rarity.Rare)) : Rarity.Common);
			List<PrefabRef> list5 = rarity switch
			{
				Rarity.Rare => list3, 
				Rarity.Uncommon => list2, 
				Rarity.Common => list, 
				_ => list4, 
			};
			if (list5.Count == 0)
			{
				CatsPlugin.Log.LogDebug((object)$"[Cats] rolled {rarity} but that pool is empty");
				continue;
			}
			PrefabRef val3 = list5[Random.Range(0, list5.Count)];
			ValuableObject val4 = (((Object)(object)((PrefabRef<GameObject>)(object)val3).Prefab != (Object)null) ? ((PrefabRef<GameObject>)(object)val3).Prefab.GetComponent<ValuableObject>() : null);
			if (!((Object)(object)val4 == (Object)null))
			{
				if (!volumesByType.TryGetValue(val4.volumeType, out var value5) || value5.Count == 0)
				{
					CatsPlugin.Log.LogDebug((object)$"[Cats] no volumes left for {((PrefabRef<GameObject>)(object)val3).PrefabName} (type {val4.volumeType})");
					continue;
				}
				int num8 = Random.Range(0, value5.Count);
				CatsPlugin.Log.LogInfo((object)$"[Cats] spawning {((PrefabRef<GameObject>)(object)val3).PrefabName} at volume slot {num8}");
				Valuables.SpawnValuable(val3, value5[num8].Item1, value5[num8].Item2);
				value5.RemoveAt(num8);
				num5++;
			}
		}
		CatsPlugin.Log.LogInfo((object)$"[Cats] spawned {num5}/{value} cats ({num6} attempts)");
		if (num5 > 0)
		{
			((MonoBehaviour)director).StartCoroutine(CatsPlugin.Instance.AssignCatNames());
		}
	}
}