Decompiled source of ExplosiveSprayPaint v1.1.5

BepInEx\plugins\ExplosiveSprayPaint\ExplosiveSprayPaint.dll

Decompiled 2 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using ExplosiveSprayPaint.Config;
using ExplosiveSprayPaint.Networking;
using ExplosiveSprayPaint.Patches;
using ExplosiveSprayPaint.Utilities;
using GameNetcodeStuff;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Unity.Collections;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.Rendering.HighDefinition;

[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("ExplosiveSprayPaint")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("ExplosiveSprayPaint")]
[assembly: AssemblyTitle("ExplosiveSprayPaint")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace ExplosiveSprayPaint
{
	[BepInPlugin("huntedbyacreature.explosivespraypaint", "ExplosiveSprayPaint", "1.1.5")]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string ModGuid = "huntedbyacreature.explosivespraypaint";

		public const string ModName = "ExplosiveSprayPaint";

		public const string ModVersion = "1.1.5";

		private Harmony? _harmony;

		internal static Plugin Instance { get; private set; }

		internal static ManualLogSource Log { get; private set; }

		internal static ExplosiveSprayPaintConfig ModConfig { get; private set; }

		private void Awake()
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			ModConfig = new ExplosiveSprayPaintConfig(((BaseUnityPlugin)this).Config);
			_harmony = new Harmony("huntedbyacreature.explosivespraypaint");
			SprayPaintItemPatches.Apply(_harmony);
			_harmony.PatchAll(typeof(Plugin).Assembly);
			SprayPaintRuntimeWatcher.Register();
			SprayCanExplosionNetworking.Register();
			Log.LogInfo((object)string.Format("{0} {1} loaded. DebugLogging={2}, TreatSprayUseAsShake={3}, GlowInTheDarkPaint={4}, FunnyExplosionPhysics={5}, ExplosionChance={6:0.##}%.", "ExplosiveSprayPaint", "1.1.5", ModConfig.EnableDebugLogging.Value, ModConfig.TreatSprayUseAsShake.Value, ModConfig.GlowInTheDarkPaint.Value, ModConfig.EnableFunnyExplosionPhysics.Value, ModConfig.ExplosionChancePercent.Value));
		}

		private void Update()
		{
			SprayPaintRuntimeWatcher.Tick();
		}

		private void OnDestroy()
		{
			ManualLogSource log = Log;
			if (log != null)
			{
				log.LogInfo((object)"Plugin component OnDestroy called; leaving runtime hooks active for this session.");
			}
		}
	}
}
namespace ExplosiveSprayPaint.Utilities
{
	internal static class ExplosionEffectUtility
	{
		private const int EnemyCollisionMask = 524288;

		private const float FunnyNormalPhysicsForce = 35f;

		private const float FunnyCatastrophicPhysicsForce = 85f;

		private const float FunnyNormalPlayerKnockback = 13f;

		private const float FunnyCatastrophicPlayerKnockback = 32f;

		private const float FunnyNormalVerticalKnockback = 5f;

		private const float FunnyCatastrophicVerticalKnockback = 12f;

		internal static Vector3 GetExplosionPosition(SprayPaintItem sprayPaintItem)
		{
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: 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_0091: 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_002e: 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_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: 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)
			Transform transform = ((Component)sprayPaintItem).transform;
			PlayerControllerB playerHeldBy = ((GrabbableObject)sprayPaintItem).playerHeldBy;
			if ((Object)(object)playerHeldBy != (Object)null)
			{
				if (!((Object)(object)playerHeldBy.gameplayCamera != (Object)null))
				{
					return ((Component)playerHeldBy).transform.position + Vector3.up * 1.2f + ((Component)playerHeldBy).transform.forward * 0.35f;
				}
				return ((Component)playerHeldBy.gameplayCamera).transform.position + ((Component)playerHeldBy.gameplayCamera).transform.forward * 0.35f - Vector3.up * 0.25f;
			}
			return transform.position;
		}

		internal static void PlayClientSideExplosion(ExplosionMessage message, SprayPaintItem? sprayPaintItem)
		{
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: 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_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: 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)
			if (Plugin.ModConfig.EnableDebugLogging.Value)
			{
				Plugin.Log.LogInfo((object)$"Playing client explosion. catastrophic={message.Catastrophic}, blastRadius={message.BlastRadius:0.00}, paintRadius={message.PaintRadius:0.00}, paintCount={message.PaintCount}, color={ColorUtility.ToHtmlStringRGBA(message.PaintColor)}, hasSprayItem={(Object)(object)sprayPaintItem != (Object)null}.");
			}
			TrySpawnVanillaExplosion(message.Position, message.BlastRadius, message.PhysicsForce);
			PaintDecalUtility.SpawnPaintBurst(sprayPaintItem, message.Position, message.PaintColor, message.PaintRadius, message.PaintCount, message.RandomSeed);
			ParticleUtility.SpawnPaintParticles(message.Position, message.PaintColor, message.BlastRadius, message.Catastrophic);
			TryShakeCamera(message.Position, message.BlastRadius, message.Catastrophic);
			TryShowHudNotification(message);
		}

		internal static void ApplyServerSideDamageAndNoise(ExplosionMessage message)
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			float blastRadius = message.BlastRadius;
			int damage = (message.Catastrophic ? Plugin.ModConfig.CatastrophicPlayerDamage.Value : Plugin.ModConfig.NormalPlayerDamage.Value);
			int damage2 = (message.Catastrophic ? Plugin.ModConfig.CatastrophicEnemyDamage.Value : Plugin.ModConfig.NormalEnemyDamage.Value);
			DamageNearbyPlayers(message.Position, blastRadius, damage, message.Catastrophic);
			DamageNearbyEnemies(message.Position, blastRadius, damage2);
			RoundManager instance = RoundManager.Instance;
			if (instance != null)
			{
				instance.PlayAudibleNoise(message.Position, message.Catastrophic ? (blastRadius * 2.5f) : (blastRadius * 1.6f), message.Catastrophic ? 1f : 0.55f, 0, false, 0);
			}
		}

		private static void TrySpawnVanillaExplosion(Vector3 position, float radius, float physicsForce)
		{
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				MethodInfo methodInfo = AccessTools.Method(typeof(Landmine), "SpawnExplosion", (Type[])null, (Type[])null);
				if (methodInfo == null)
				{
					return;
				}
				ParameterInfo[] parameters = methodInfo.GetParameters();
				object[] array = new object[parameters.Length];
				for (int i = 0; i < parameters.Length; i++)
				{
					string text = parameters[i].Name ?? string.Empty;
					object[] array2 = array;
					int num = i;
					object obj;
					switch (text)
					{
					case "explosionPosition":
					case "position":
						obj = position;
						break;
					case "spawnExplosionEffect":
						obj = true;
						break;
					case "killRange":
						obj = 0f;
						break;
					case "damageRange":
						obj = radius;
						break;
					case "nonLethalDamage":
					case "damage":
						obj = 0;
						break;
					case "physicsForce":
						obj = physicsForce;
						break;
					case "overridePrefab":
						obj = null;
						break;
					case "goThroughCar":
						obj = true;
						break;
					default:
						obj = (parameters[i].HasDefaultValue ? parameters[i].DefaultValue : GetDefaultValue(parameters[i].ParameterType));
						break;
					}
					array2[num] = obj;
				}
				methodInfo.Invoke(null, array);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Could not spawn vanilla explosion effect: " + ex.Message));
			}
		}

		private static void DamageNearbyPlayers(Vector3 position, float radius, int damage, bool catastrophic)
		{
			//IL_0050: 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_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: 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_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			if (damage <= 0 || StartOfRound.Instance?.allPlayerScripts == null)
			{
				return;
			}
			PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts;
			foreach (PlayerControllerB val in allPlayerScripts)
			{
				if ((Object)(object)val == (Object)null || !val.isPlayerControlled || val.isPlayerDead)
				{
					continue;
				}
				float num = Vector3.Distance(position, ((Component)val).transform.position);
				if (!(num > radius))
				{
					float num2 = Mathf.Clamp01(1f - num / Mathf.Max(radius, 0.01f));
					int damage2 = Mathf.Max(1, Mathf.RoundToInt((float)damage * Mathf.Lerp(0.45f, 1f, num2)));
					Vector3 val2 = ((Component)val).transform.position - position;
					val2.y = 0f;
					if (((Vector3)(ref val2)).sqrMagnitude < 0.001f)
					{
						val2 = ((Component)val).transform.forward;
					}
					float num3 = (catastrophic ? GetCatastrophicPlayerKnockback() : GetNormalPlayerKnockback());
					Vector3 val3 = ((Vector3)(ref val2)).normalized * num3;
					val3.y = GetVerticalPlayerKnockback(catastrophic);
					try
					{
						InvokeDamagePlayer(val, damage2, val3);
						SprayPaintIntrospection.AddExternalForce(val, Plugin.ModConfig.EnableFunnyExplosionPhysics.Value ? val3 : ClampPlayerForce(val3));
					}
					catch (Exception ex)
					{
						Plugin.Log.LogWarning((object)("Could not damage player " + val.playerUsername + ": " + ex.Message));
					}
				}
			}
		}

		private static void DamageNearbyEnemies(Vector3 position, float radius, int damage)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			if (damage <= 0)
			{
				return;
			}
			HashSet<EnemyAI> hashSet = new HashSet<EnemyAI>();
			Collider[] array = Physics.OverlapSphere(position, radius, 524288, (QueryTriggerInteraction)2);
			for (int i = 0; i < array.Length; i++)
			{
				EnemyAI componentInParent = ((Component)array[i]).GetComponentInParent<EnemyAI>();
				if (!((Object)(object)componentInParent == (Object)null) && !componentInParent.isEnemyDead && hashSet.Add(componentInParent))
				{
					try
					{
						InvokeHitEnemy(componentInParent, damage);
					}
					catch (Exception ex)
					{
						Plugin.Log.LogWarning((object)("Could not damage enemy " + componentInParent.enemyType?.enemyName + ": " + ex.Message));
					}
				}
			}
		}

		private static void TryShakeCamera(Vector3 position, float radius, bool catastrophic)
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			if (!Plugin.ModConfig.EnableScreenShake.Value || (Object)(object)GameNetworkManager.Instance?.localPlayerController == (Object)null || Vector3.Distance(((Component)GameNetworkManager.Instance.localPlayerController).transform.position, position) > radius * 1.75f)
			{
				return;
			}
			try
			{
				HUDManager instance = HUDManager.Instance;
				if (instance != null)
				{
					instance.ShakeCamera((ScreenShakeType)catastrophic);
				}
			}
			catch
			{
			}
		}

		private static void TryShowHudNotification(ExplosionMessage message)
		{
			if (!Plugin.ModConfig.EnableHudNotification.Value || (Object)(object)GameNetworkManager.Instance?.localPlayerController == (Object)null || GameNetworkManager.Instance.localPlayerController.actualClientId != message.HolderClientId)
			{
				return;
			}
			try
			{
				HUDManager instance = HUDManager.Instance;
				if (instance != null)
				{
					instance.DisplayTip("Explosive Spray Paint", "The can ruptured!", true, false, "ESP_CanRuptured");
				}
			}
			catch
			{
			}
		}

		internal static float GetBlastRadius(bool catastrophic)
		{
			return Mathf.Clamp(catastrophic ? Plugin.ModConfig.CatastrophicBlastRadius.Value : Plugin.ModConfig.NormalBlastRadius.Value, 0.5f, catastrophic ? 8f : 4.5f);
		}

		internal static float GetPhysicsForce(bool catastrophic)
		{
			if (Plugin.ModConfig.EnableFunnyExplosionPhysics.Value)
			{
				if (!catastrophic)
				{
					return 35f;
				}
				return 85f;
			}
			return Mathf.Clamp(catastrophic ? Plugin.ModConfig.CatastrophicPhysicsForce.Value : Plugin.ModConfig.NormalPhysicsForce.Value, 0f, catastrophic ? 6f : 3f);
		}

		internal static float GetPaintRadius(bool catastrophic)
		{
			return Mathf.Clamp(catastrophic ? Plugin.ModConfig.CatastrophicPaintSplatterRadius.Value : Plugin.ModConfig.NormalPaintSplatterRadius.Value, 0.5f, catastrophic ? 12f : 7f);
		}

		internal static int GetPaintCount(bool catastrophic)
		{
			return Mathf.Clamp(catastrophic ? Plugin.ModConfig.CatastrophicPaintSplats.Value : Plugin.ModConfig.NormalPaintSplats.Value, 0, catastrophic ? 240 : 140);
		}

		private static Vector3 ClampPlayerForce(Vector3 force)
		{
			//IL_0002: 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_0036: 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_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = default(Vector3);
			((Vector3)(ref val))..ctor(force.x, 0f, force.z);
			float num = 3f;
			if (((Vector3)(ref val)).magnitude > num)
			{
				val = ((Vector3)(ref val)).normalized * num;
			}
			return new Vector3(val.x, Mathf.Clamp(force.y, -0.1f, Plugin.ModConfig.MaxVerticalKnockback.Value), val.z);
		}

		private static float GetNormalPlayerKnockback()
		{
			if (!Plugin.ModConfig.EnableFunnyExplosionPhysics.Value)
			{
				return Plugin.ModConfig.NormalPlayerKnockback.Value;
			}
			return 13f;
		}

		private static float GetCatastrophicPlayerKnockback()
		{
			if (!Plugin.ModConfig.EnableFunnyExplosionPhysics.Value)
			{
				return Plugin.ModConfig.CatastrophicPlayerKnockback.Value;
			}
			return 32f;
		}

		private static float GetVerticalPlayerKnockback(bool catastrophic)
		{
			if (Plugin.ModConfig.EnableFunnyExplosionPhysics.Value)
			{
				if (!catastrophic)
				{
					return 5f;
				}
				return 12f;
			}
			return Mathf.Min(Plugin.ModConfig.MaxVerticalKnockback.Value, catastrophic ? 0.7f : 0.35f);
		}

		private static void InvokeDamagePlayer(PlayerControllerB player, int damage, Vector3 force)
		{
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			MethodInfo methodInfo = AccessTools.Method(typeof(PlayerControllerB), "DamagePlayer", (Type[])null, (Type[])null);
			if (methodInfo == null)
			{
				return;
			}
			ParameterInfo[] parameters = methodInfo.GetParameters();
			object[] array = new object[parameters.Length];
			for (int i = 0; i < parameters.Length; i++)
			{
				string text = parameters[i].Name ?? string.Empty;
				object[] array2 = array;
				int num = i;
				object obj;
				switch (text)
				{
				case "damageNumber":
				case "damage":
					obj = damage;
					break;
				case "hasDamageSFX":
					obj = true;
					break;
				case "callRPC":
					obj = true;
					break;
				case "causeOfDeath":
					obj = (object)(CauseOfDeath)0;
					break;
				case "deathAnimation":
					obj = 0;
					break;
				case "fallDamage":
					obj = false;
					break;
				case "force":
					obj = force;
					break;
				default:
					obj = (parameters[i].HasDefaultValue ? parameters[i].DefaultValue : GetDefaultValue(parameters[i].ParameterType));
					break;
				}
				array2[num] = obj;
			}
			methodInfo.Invoke(player, array);
		}

		private static void InvokeHitEnemy(EnemyAI enemy, int damage)
		{
			MethodInfo methodInfo = AccessTools.Method(((object)enemy).GetType(), "HitEnemy", (Type[])null, (Type[])null);
			if (methodInfo == null)
			{
				return;
			}
			ParameterInfo[] parameters = methodInfo.GetParameters();
			object[] array = new object[parameters.Length];
			for (int i = 0; i < parameters.Length; i++)
			{
				string text = parameters[i].Name ?? string.Empty;
				object[] array2 = array;
				int num = i;
				object obj;
				switch (text)
				{
				case "force":
				case "damage":
					obj = damage;
					break;
				case "playerWhoHit":
					obj = null;
					break;
				case "playHitSFX":
					obj = true;
					break;
				case "hitID":
					obj = -1;
					break;
				default:
					obj = (parameters[i].HasDefaultValue ? parameters[i].DefaultValue : GetDefaultValue(parameters[i].ParameterType));
					break;
				}
				array2[num] = obj;
			}
			methodInfo.Invoke(enemy, array);
		}

		private static object? GetDefaultValue(Type type)
		{
			if (!type.IsValueType)
			{
				return null;
			}
			return Activator.CreateInstance(type);
		}
	}
	internal static class PaintDecalUtility
	{
		private const float SurfaceOffset = 0.018f;

		internal static void SpawnPaintBurst(SprayPaintItem? sprayPaintItem, Vector3 origin, Color color, float radius, int count, int seed)
		{
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			if (count <= 0 || radius <= 0f)
			{
				return;
			}
			GameObject val = TryGetPaintPrefab(sprayPaintItem);
			State state = Random.state;
			Random.InitState(seed);
			int num = 0;
			int num2 = 0;
			int num3 = 0;
			int num4 = 0;
			int num5 = 0;
			int num6 = count * 5;
			LogDebug($"Paint burst starting. origin={origin}, radius={radius:0.00}, targetCount={count}, color={ColorUtility.ToHtmlStringRGBA(color)}, hasSprayItem={(Object)(object)sprayPaintItem != (Object)null}, hasVanillaPrefab={(Object)(object)val != (Object)null}.");
			try
			{
				for (int i = 0; i < num6; i++)
				{
					if (num >= count)
					{
						break;
					}
					if (!TryFindPaintSurface(origin, radius, out var hit))
					{
						num3++;
						continue;
					}
					num2++;
					float size = Random.Range(0.28f, 0.95f) * ((Random.value < 0.12f) ? 1.45f : 1f);
					if (Plugin.ModConfig.UseVanillaPaintPlacement.Value && (Object)(object)sprayPaintItem != (Object)null && SprayPaintIntrospection.TryAddVanillaPaint(sprayPaintItem, ((RaycastHit)(ref hit)).point, ((RaycastHit)(ref hit)).normal))
					{
						num4++;
					}
					SpawnSingleSplat(val, hit, color, size);
					num5++;
					num++;
				}
				LogDebug($"Paint burst finished. attempts={num6}, raycastHits={num2}, rejectedHits={num3}, visibleSplats={num}/{count}, vanillaPlacements={num4}, fallbackSplats={num5}.");
			}
			finally
			{
				Random.state = state;
			}
		}

		private static bool TryFindPaintSurface(Vector3 origin, float radius, out RaycastHit hit)
		{
			//IL_0006: 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_001a: 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_0036: 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_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: 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)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: 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_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			float value = Random.value;
			Vector2 val = Random.insideUnitCircle * radius;
			if (value < 0.34f)
			{
				return TryRaycastPaintSurface(origin + new Vector3(val.x, 2.2f + Random.Range(0f, 0.7f), val.y), Vector3.down, 5.5f, out hit);
			}
			if (value < 0.74f)
			{
				Vector2 insideUnitCircle = Random.insideUnitCircle;
				Vector3 val2 = Vector2.op_Implicit(((Vector2)(ref insideUnitCircle)).normalized);
				if (((Vector3)(ref val2)).sqrMagnitude < 0.01f)
				{
					val2 = Vector2.op_Implicit(Vector2.right);
				}
				Vector3 val3 = new Vector3(val2.x, Random.Range(-0.2f, 0.35f), val2.y);
				Vector3 normalized = ((Vector3)(ref val3)).normalized;
				return TryRaycastPaintSurface(origin + Vector3.up * Random.Range(-0.2f, 1.4f), normalized, radius + 2f, out hit);
			}
			Vector3 onUnitSphere = Random.onUnitSphere;
			if (onUnitSphere.y > 0.75f)
			{
				onUnitSphere.y *= -1f;
			}
			return TryRaycastPaintSurface(origin + Random.insideUnitSphere * 0.35f, ((Vector3)(ref onUnitSphere)).normalized, radius + 2.5f, out hit);
		}

		private static bool TryRaycastPaintSurface(Vector3 origin, Vector3 direction, float distance, out RaycastHit hit)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: 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_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			RaycastHit[] array = Physics.RaycastAll(origin, ((Vector3)(ref direction)).normalized, distance, -1, (QueryTriggerInteraction)1);
			Array.Sort(array, (RaycastHit left, RaycastHit right) => ((RaycastHit)(ref left)).distance.CompareTo(((RaycastHit)(ref right)).distance));
			RaycastHit[] array2 = array;
			foreach (RaycastHit val in array2)
			{
				if (IsValidPaintSurface(val))
				{
					hit = val;
					return true;
				}
			}
			hit = default(RaycastHit);
			return false;
		}

		private static bool IsValidPaintSurface(RaycastHit hit)
		{
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			Collider collider = ((RaycastHit)(ref hit)).collider;
			if ((Object)(object)collider == (Object)null || !collider.enabled || collider.isTrigger)
			{
				return false;
			}
			if ((Object)(object)((Component)collider).GetComponentInParent<PlayerControllerB>() != (Object)null || (Object)(object)((Component)collider).GetComponentInParent<GrabbableObject>() != (Object)null || (Object)(object)((Component)collider).GetComponentInParent<EnemyAI>() != (Object)null)
			{
				return false;
			}
			Renderer val = ((Component)collider).GetComponent<Renderer>() ?? ((Component)collider).GetComponentInParent<Renderer>() ?? ((Component)collider).GetComponentInChildren<Renderer>();
			if ((Object)(object)val == (Object)null || !val.enabled)
			{
				return false;
			}
			Vector3 normal = ((RaycastHit)(ref hit)).normal;
			return ((Vector3)(ref normal)).sqrMagnitude > 0.8f;
		}

		private static GameObject? TryGetPaintPrefab(SprayPaintItem? sprayPaintItem)
		{
			if ((Object)(object)sprayPaintItem == (Object)null)
			{
				return null;
			}
			return SprayPaintIntrospection.GetObjectField<GameObject>(sprayPaintItem, new string[3] { "sprayPaintPrefab", "paintPrefab", "sprayDecalPrefab" });
		}

		private static void SpawnSingleSplat(GameObject? vanillaPaintPrefab, RaycastHit hit, Color color, float size)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			GameObject obj = SpawnFallbackSplat(hit, color, size * Random.Range(0.85f, 1.25f));
			((Object)obj).name = "ExplosiveSprayPaint_VisibleSplat";
			obj.AddComponent<TemporaryObject>().Initialize(Plugin.ModConfig.PaintLifetimeSeconds.Value, destroyInstancedMaterials: true);
		}

		private static GameObject SpawnFallbackSplat(RaycastHit hit, Color color, float size)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_000d: 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_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: 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_0043: 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_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("ExplosiveSprayPaint_FallbackSplat");
			Vector3 normal = ((RaycastHit)(ref hit)).normal;
			Vector3 normalized = ((Vector3)(ref normal)).normalized;
			val.transform.position = ((RaycastHit)(ref hit)).point + normalized * 0.018f;
			val.transform.rotation = SurfaceRotationForQuad(normalized);
			val.transform.Rotate(Vector3.forward, Random.Range(0f, 360f), (Space)1);
			val.transform.SetParent(((Component)((RaycastHit)(ref hit)).collider).transform, true);
			GameObject obj = GameObject.CreatePrimitive((PrimitiveType)5);
			((Object)obj).name = "PaintQuad";
			obj.transform.SetParent(val.transform, false);
			obj.transform.localPosition = Vector3.zero;
			obj.transform.localRotation = Quaternion.identity;
			obj.transform.localScale = new Vector3(size, size * Random.Range(0.55f, 1.25f), 1f);
			RemoveColliders(obj);
			obj.GetComponent<Renderer>().material = CreateQuadMaterial(color, Random.Range(0, int.MaxValue));
			return val;
		}

		private static Material CreateQuadMaterial(Color color, int seed)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_000b: 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)
			Material val = new Material(FindPaintShader());
			Texture2D val3 = (Texture2D)(object)(val.mainTexture = (Texture)(object)CreateSplatTexture(color, seed));
			ApplyColor(val, Color.white);
			DisableEmission(val);
			val.renderQueue = 3000;
			if (val.HasProperty("_SurfaceType"))
			{
				val.SetFloat("_SurfaceType", 1f);
				val.EnableKeyword("_SURFACE_TYPE_TRANSPARENT");
			}
			if (val.HasProperty("_BlendMode"))
			{
				val.SetFloat("_BlendMode", 0f);
			}
			if (val.HasProperty("_SrcBlend"))
			{
				val.SetFloat("_SrcBlend", 5f);
			}
			if (val.HasProperty("_DstBlend"))
			{
				val.SetFloat("_DstBlend", 10f);
			}
			if (val.HasProperty("_ZWrite"))
			{
				val.SetFloat("_ZWrite", 0f);
			}
			if (val.HasProperty("_BaseColorMap"))
			{
				val.SetTexture("_BaseColorMap", (Texture)(object)val3);
			}
			if (val.HasProperty("_UnlitColorMap"))
			{
				val.SetTexture("_UnlitColorMap", (Texture)(object)val3);
			}
			if (val.HasProperty("_CullMode"))
			{
				val.SetFloat("_CullMode", 0f);
			}
			if (val.HasProperty("_Cull"))
			{
				val.SetFloat("_Cull", 0f);
			}
			return val;
		}

		private static Shader FindPaintShader()
		{
			if (Plugin.ModConfig.GlowInTheDarkPaint.Value)
			{
				return Shader.Find("Sprites/Default") ?? Shader.Find("Unlit/Transparent") ?? Shader.Find("HDRP/Unlit") ?? Shader.Find("Standard");
			}
			return Shader.Find("HDRP/Lit") ?? Shader.Find("Standard") ?? Shader.Find("Sprites/Default") ?? Shader.Find("Unlit/Transparent");
		}

		private static Texture2D CreateSplatTexture(Color color, int seed)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: 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_0025: Expected O, but got Unknown
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: 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_0144: 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)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = new Texture2D(64, 64, (TextureFormat)4, false)
			{
				name = "ExplosiveSprayPaint_SplatTexture",
				wrapMode = (TextureWrapMode)1,
				filterMode = (FilterMode)1
			};
			State state = Random.state;
			Random.InitState(seed);
			Vector2 val2 = default(Vector2);
			((Vector2)(ref val2))..ctor(63f * Random.Range(0.43f, 0.57f), 63f * Random.Range(0.43f, 0.57f));
			float num = Random.Range(17f, 25f);
			float num2 = Random.Range(0.8f, 1.25f);
			float num3 = Random.Range(0.75f, 1.25f);
			Vector2 val3 = default(Vector2);
			for (int i = 0; i < 64; i++)
			{
				for (int j = 0; j < 64; j++)
				{
					((Vector2)(ref val3))..ctor(((float)j - val2.x) / num2, ((float)i - val2.y) / num3);
					float magnitude = ((Vector2)(ref val3)).magnitude;
					float num4 = Mathf.PerlinNoise((float)j * 0.16f + (float)seed * 0.001f, (float)i * 0.16f - (float)seed * 0.001f);
					float num5 = Mathf.Clamp01((num * Mathf.Lerp(0.72f, 1.22f, num4) - magnitude) / 5.5f);
					for (int k = 0; k < 5; k++)
					{
						float num6 = (float)k / 5f * MathF.PI * 2f + (float)seed * 0.0001f;
						Vector2 val4 = val2 + new Vector2(Mathf.Cos(num6), Mathf.Sin(num6)) * Random.Range(15f, 27f);
						float num7 = Vector2.Distance(new Vector2((float)j, (float)i), val4);
						num5 = Mathf.Max(num5, Mathf.Clamp01((Random.Range(3f, 7f) - num7) / 2f));
					}
					Color val5 = color;
					val5.a = num5 * 0.94f;
					val.SetPixel(j, i, val5);
				}
			}
			val.Apply(false, false);
			Random.state = state;
			return val;
		}

		private static void LogDebug(string message)
		{
			if (Plugin.ModConfig.EnableDebugLogging.Value)
			{
				Plugin.Log.LogInfo((object)message);
			}
		}

		private static void ApplyColor(Material material, Color color)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			material.color = color;
			if (material.HasProperty("_BaseColor"))
			{
				material.SetColor("_BaseColor", color);
			}
			if (material.HasProperty("_Color"))
			{
				material.SetColor("_Color", color);
			}
		}

		private static void DisableEmission(Material material)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			material.DisableKeyword("_EMISSION");
			material.DisableKeyword("_EMISSIVE_COLOR_MAP");
			if (material.HasProperty("_EmissionColor"))
			{
				material.SetColor("_EmissionColor", Color.black);
			}
			if (material.HasProperty("_EmissiveColor"))
			{
				material.SetColor("_EmissiveColor", Color.black);
			}
			if (material.HasProperty("_EmissiveIntensity"))
			{
				material.SetFloat("_EmissiveIntensity", 0f);
			}
		}

		private static Quaternion SurfaceRotationForQuad(Vector3 normal)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: 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)
			return Quaternion.LookRotation(normal, GetStableUp(normal));
		}

		private static Vector3 GetStableUp(Vector3 normal)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//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_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: 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_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = Vector3.Cross(normal, Vector3.up);
			if (((Vector3)(ref val)).sqrMagnitude < 0.01f)
			{
				val = Vector3.Cross(normal, Vector3.right);
			}
			Vector3 val2 = Vector3.Cross(((Vector3)(ref val)).normalized, normal);
			return ((Vector3)(ref val2)).normalized;
		}

		private static void RemoveColliders(GameObject gameObject)
		{
			Collider[] componentsInChildren = gameObject.GetComponentsInChildren<Collider>();
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				Object.Destroy((Object)(object)componentsInChildren[i]);
			}
		}
	}
	internal static class ParticleUtility
	{
		internal static void SpawnPaintParticles(Vector3 position, Color paintColor, float radius, bool catastrophic)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: 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_0016: 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_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: 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_005c: 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_00a0: 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_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: 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_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Expected O, but got Unknown
			GameObject val = new GameObject("ExplosiveSprayPaint_Particles");
			val.transform.position = position;
			ParticleSystem obj = val.AddComponent<ParticleSystem>();
			MainModule main = obj.main;
			((MainModule)(ref main)).startColor = MinMaxGradient.op_Implicit(paintColor);
			((MainModule)(ref main)).startLifetime = MinMaxCurve.op_Implicit(catastrophic ? 1.3f : 0.8f);
			((MainModule)(ref main)).startSpeed = MinMaxCurve.op_Implicit(catastrophic ? 12f : 6f);
			((MainModule)(ref main)).startSize = MinMaxCurve.op_Implicit(catastrophic ? 0.22f : 0.12f);
			((MainModule)(ref main)).maxParticles = (catastrophic ? 450 : 180);
			((MainModule)(ref main)).simulationSpace = (ParticleSystemSimulationSpace)1;
			EmissionModule emission = obj.emission;
			((EmissionModule)(ref emission)).enabled = false;
			ShapeModule shape = obj.shape;
			((ShapeModule)(ref shape)).enabled = true;
			((ShapeModule)(ref shape)).shapeType = (ParticleSystemShapeType)0;
			((ShapeModule)(ref shape)).radius = 0.25f;
			CollisionModule collision = obj.collision;
			((CollisionModule)(ref collision)).enabled = true;
			((CollisionModule)(ref collision)).type = (ParticleSystemCollisionType)1;
			((CollisionModule)(ref collision)).dampen = MinMaxCurve.op_Implicit(0.55f);
			((CollisionModule)(ref collision)).bounce = MinMaxCurve.op_Implicit(0.15f);
			((CollisionModule)(ref collision)).lifetimeLoss = MinMaxCurve.op_Implicit(0.35f);
			ParticleSystemRenderer component = ((Component)obj).GetComponent<ParticleSystemRenderer>();
			component.renderMode = (ParticleSystemRenderMode)0;
			((Renderer)component).material = new Material(Shader.Find("Sprites/Default"));
			obj.Emit(catastrophic ? 160 : 65);
			val.AddComponent<TemporaryObject>().Initialize(catastrophic ? 4f : 2.5f, destroyInstancedMaterials: true);
		}
	}
	internal static class SprayPaintIntrospection
	{
		private const int TextureSampleSize = 16;

		private static readonly string[] ColorPropertyNames = new string[4] { "_BaseColor", "_Color", "_TintColor", "_EmissionColor" };

		private static readonly string[] TexturePropertyNames = new string[6] { "_BaseColorMap", "_MainTex", "_UnlitColorMap", "_BaseMap", "_DecalColorMap", "_EmissionMap" };

		internal static Color GetCurrentSprayColor(SprayPaintItem sprayPaintItem)
		{
			//IL_0070: 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_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			int valueOrDefault = TryReadInt(sprayPaintItem, "sprayCanMatsIndex", "sprayPaintColorIndex", "colorIndex", "materialIndex").GetValueOrDefault(-1);
			if (TryGetIndexedMaterialColor(sprayPaintItem, valueOrDefault, "particleMats", new string[4] { "particleMats", "sprayParticleMats", "sprayPaintParticleMaterials", "particleMaterials" }, out Color color, out string source))
			{
				return LogResolvedColor(sprayPaintItem, color, valueOrDefault, source);
			}
			Color? val = TryReadColor(sprayPaintItem, "sprayPaintColor", "currentColor", "paintColor", "sprayColor");
			if (val.HasValue)
			{
				return LogResolvedColor(sprayPaintItem, val.Value, valueOrDefault, "direct color field");
			}
			if (TryGetIndexedMaterialColor(sprayPaintItem, valueOrDefault, "sprayCanMats", new string[3] { "sprayCanMats", "sprayPaintMaterials", "sprayCanMaterials" }, out Color color2, out string source2))
			{
				return LogResolvedColor(sprayPaintItem, color2, valueOrDefault, source2);
			}
			if (TryGetRendererColor(sprayPaintItem, out Color color3, out string source3))
			{
				return LogResolvedColor(sprayPaintItem, color3, valueOrDefault, source3);
			}
			return LogResolvedColor(sprayPaintItem, Color.magenta, valueOrDefault, "fallback magenta");
		}

		internal static T? GetObjectField<T>(object instance, params string[] names) where T : class
		{
			Type type = instance.GetType();
			foreach (string text in names)
			{
				if (AccessTools.Field(type, text)?.GetValue(instance) is T result)
				{
					return result;
				}
				PropertyInfo propertyInfo = AccessTools.Property(type, text);
				if ((object)propertyInfo != null && propertyInfo.CanRead && propertyInfo.GetValue(instance) is T result2)
				{
					return result2;
				}
			}
			return null;
		}

		internal static float? GetFloatField(object instance, params string[] names)
		{
			Type type = instance.GetType();
			foreach (string text in names)
			{
				object obj = AccessTools.Field(type, text)?.GetValue(instance);
				if (obj is float)
				{
					return (float)obj;
				}
				PropertyInfo propertyInfo = AccessTools.Property(type, text);
				object obj2 = (((object)propertyInfo != null && propertyInfo.CanRead) ? propertyInfo.GetValue(instance) : null);
				if (obj2 is float)
				{
					return (float)obj2;
				}
			}
			return null;
		}

		internal static bool? GetBoolField(object instance, params string[] names)
		{
			Type type = instance.GetType();
			foreach (string text in names)
			{
				object obj = AccessTools.Field(type, text)?.GetValue(instance);
				if (obj is bool)
				{
					return (bool)obj;
				}
				PropertyInfo propertyInfo = AccessTools.Property(type, text);
				object obj2 = (((object)propertyInfo != null && propertyInfo.CanRead) ? propertyInfo.GetValue(instance) : null);
				if (obj2 is bool)
				{
					return (bool)obj2;
				}
			}
			return null;
		}

		internal static void DestroySprayCanSafely(SprayPaintItem sprayPaintItem)
		{
			try
			{
				StopSprayingSafely(sprayPaintItem);
				if ((Object)(object)((GrabbableObject)sprayPaintItem).playerHeldBy != (Object)null)
				{
					MethodInfo methodInfo = AccessTools.Method(((object)sprayPaintItem).GetType(), "DestroyObjectInHand", (Type[])null, (Type[])null);
					if (methodInfo != null)
					{
						ParameterInfo[] parameters = methodInfo.GetParameters();
						object[] array = new object[parameters.Length];
						for (int i = 0; i < parameters.Length; i++)
						{
							array[i] = ((i == 0) ? ((GrabbableObject)sprayPaintItem).playerHeldBy : (parameters[i].HasDefaultValue ? parameters[i].DefaultValue : GetDefaultValue(parameters[i].ParameterType)));
						}
						methodInfo.Invoke(sprayPaintItem, array);
						return;
					}
				}
				NetworkObject networkObject = ((NetworkBehaviour)sprayPaintItem).NetworkObject;
				if ((Object)(object)networkObject != (Object)null && networkObject.IsSpawned)
				{
					networkObject.Despawn(true);
				}
				else
				{
					Object.Destroy((Object)(object)((Component)sprayPaintItem).gameObject);
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Could not destroy ruptured spray can through normal path: " + ex.Message));
				try
				{
					Object.Destroy((Object)(object)((Component)sprayPaintItem).gameObject);
				}
				catch
				{
				}
			}
		}

		internal static void StopSprayingSafely(SprayPaintItem sprayPaintItem)
		{
			try
			{
				AccessTools.Method(((object)sprayPaintItem).GetType(), "StopSpraying", (Type[])null, (Type[])null)?.Invoke(sprayPaintItem, Array.Empty<object>());
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Could not call StopSpraying before rupture cleanup: " + ex.Message));
			}
			TrySetBoolField(sprayPaintItem, false, "isSpraying", "tryingToUseEmptyCan", "makingAudio");
			AudioSource objectField = GetObjectField<AudioSource>(sprayPaintItem, new string[1] { "sprayAudio" });
			if ((Object)(object)objectField != (Object)null)
			{
				objectField.Stop();
			}
			ParticleSystem objectField2 = GetObjectField<ParticleSystem>(sprayPaintItem, new string[2] { "sprayParticle", "sprayCanNeedsShakingParticle" });
			if ((Object)(object)objectField2 != (Object)null)
			{
				objectField2.Stop(true, (ParticleSystemStopBehavior)0);
			}
		}

		internal static bool TryAddVanillaPaint(SprayPaintItem sprayPaintItem, Vector3 point, Vector3 normal)
		{
			//IL_0024: 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_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: 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_0053: 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)
			try
			{
				MethodInfo methodInfo = AccessTools.Method(((object)sprayPaintItem).GetType(), "AddSprayPaintLocal", (Type[])null, (Type[])null);
				if (methodInfo == null)
				{
					return false;
				}
				Vector3 val = point + ((Vector3)(ref normal)).normalized * 0.45f;
				Vector3 val2 = -((Vector3)(ref normal)).normalized;
				object obj = methodInfo.Invoke(sprayPaintItem, new object[2] { val, val2 });
				bool flag = default(bool);
				int num;
				if (obj is bool)
				{
					flag = (bool)obj;
					num = 1;
				}
				else
				{
					num = 0;
				}
				return (byte)((uint)num & (flag ? 1u : 0u)) != 0;
			}
			catch (Exception ex)
			{
				if (Plugin.ModConfig.EnableDebugLogging.Value)
				{
					Plugin.Log.LogInfo((object)("Vanilla paint placement failed: " + ex.Message));
				}
				return false;
			}
		}

		internal static void AddExternalForce(PlayerControllerB player, Vector3 force)
		{
			//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_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: 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)
			try
			{
				FieldInfo fieldInfo = AccessTools.Field(typeof(PlayerControllerB), "externalForces");
				if (!(fieldInfo == null) && !(fieldInfo.FieldType != typeof(Vector3)))
				{
					Vector3 val = (Vector3)fieldInfo.GetValue(player);
					fieldInfo.SetValue(player, val + force);
				}
			}
			catch
			{
			}
		}

		private static Color? TryReadColor(object instance, params string[] names)
		{
			//IL_0035: 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_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: 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_0098: 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_00b0: 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_00b4: Unknown result type (might be due to invalid IL or missing references)
			Type type = instance.GetType();
			foreach (string text in names)
			{
				object obj = AccessTools.Field(type, text)?.GetValue(instance);
				if (obj is Color)
				{
					return (Color)obj;
				}
				if (obj is Color32 val)
				{
					return Color32.op_Implicit(val);
				}
				PropertyInfo propertyInfo = AccessTools.Property(type, text);
				object obj2 = (((object)propertyInfo != null && propertyInfo.CanRead) ? propertyInfo.GetValue(instance) : null);
				if (obj2 is Color)
				{
					return (Color)obj2;
				}
				if (obj2 is Color32 val2)
				{
					return Color32.op_Implicit(val2);
				}
			}
			return null;
		}

		private static int? TryReadInt(object instance, params string[] names)
		{
			Type type = instance.GetType();
			foreach (string text in names)
			{
				object obj = AccessTools.Field(type, text)?.GetValue(instance);
				if (obj is int)
				{
					return (int)obj;
				}
				PropertyInfo propertyInfo = AccessTools.Property(type, text);
				object obj2 = (((object)propertyInfo != null && propertyInfo.CanRead) ? propertyInfo.GetValue(instance) : null);
				if (obj2 is int)
				{
					return (int)obj2;
				}
			}
			return null;
		}

		private static void TrySetBoolField(object instance, bool value, params string[] names)
		{
			Type type = instance.GetType();
			foreach (string text in names)
			{
				FieldInfo fieldInfo = AccessTools.Field(type, text);
				if (fieldInfo != null && fieldInfo.FieldType == typeof(bool))
				{
					fieldInfo.SetValue(instance, value);
				}
			}
		}

		private static bool TryGetIndexedMaterialColor(SprayPaintItem sprayPaintItem, int colorIndex, string fieldLabel, string[] fieldNames, out Color color, out string source)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			color = default(Color);
			source = string.Empty;
			Material[] objectField = GetObjectField<Material[]>(sprayPaintItem, fieldNames);
			if (objectField == null || colorIndex < 0 || colorIndex >= objectField.Length || (Object)(object)objectField[colorIndex] == (Object)null)
			{
				return false;
			}
			Material val = objectField[colorIndex];
			if (!TryResolveMaterialPaintColor(val, out color, out string source2))
			{
				return false;
			}
			source = $"{fieldLabel}[{colorIndex}] {source2} ({((Object)val).name})";
			return true;
		}

		private static bool TryGetRendererColor(SprayPaintItem sprayPaintItem, out Color color, out string source)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			color = default(Color);
			source = string.Empty;
			Renderer[] componentsInChildren = ((Component)sprayPaintItem).GetComponentsInChildren<Renderer>();
			foreach (Renderer val in componentsInChildren)
			{
				if ((Object)(object)val == (Object)null || val.sharedMaterials == null)
				{
					continue;
				}
				Material[] sharedMaterials = val.sharedMaterials;
				foreach (Material val2 in sharedMaterials)
				{
					if (!((Object)(object)val2 == (Object)null) && TryResolveMaterialPaintColor(val2, out color, out string source2))
					{
						source = "renderer material " + source2 + " (" + ((Object)val2).name + ")";
						return true;
					}
				}
			}
			return false;
		}

		private static bool TryResolveMaterialPaintColor(Material material, out Color color, out string source)
		{
			//IL_0093: 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_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: 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_0031: 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)
			if (TryAverageMaterialTexture(material, out color, out source))
			{
				return true;
			}
			string[] colorPropertyNames = ColorPropertyNames;
			foreach (string text in colorPropertyNames)
			{
				if (!material.HasProperty(text))
				{
					continue;
				}
				try
				{
					color = NormalizePaintColor(material.GetColor(text));
					if (IsUsefulPaintColor(color))
					{
						source = text + " color";
						return true;
					}
				}
				catch
				{
				}
			}
			try
			{
				color = NormalizePaintColor(material.color);
				if (IsUsefulPaintColor(color))
				{
					source = "material.color";
					return true;
				}
			}
			catch
			{
			}
			color = default(Color);
			source = string.Empty;
			return false;
		}

		private static bool TryAverageMaterialTexture(Material material, out Color color, out string source)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			color = default(Color);
			source = string.Empty;
			string[] texturePropertyNames = TexturePropertyNames;
			foreach (string text in texturePropertyNames)
			{
				if (material.HasProperty(text))
				{
					Texture texture;
					try
					{
						texture = material.GetTexture(text);
					}
					catch
					{
						continue;
					}
					if (!((Object)(object)texture == (Object)null) && TryAverageTexture(texture, out color) && IsUsefulPaintColor(color))
					{
						source = text + " texture average";
						return true;
					}
				}
			}
			return false;
		}

		private static bool TryAverageTexture(Texture texture, out Color color)
		{
			Texture2D val = (Texture2D)(object)((texture is Texture2D) ? texture : null);
			if (val != null && TryAverageReadableTexture(val, out color))
			{
				return true;
			}
			return TryAverageTextureWithRenderTexture(texture, out color);
		}

		private static bool TryAverageReadableTexture(Texture2D texture, out Color color)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				return TryAverageReadableTexturePixels(texture, out color);
			}
			catch
			{
				color = default(Color);
				return false;
			}
		}

		private static bool TryAverageTextureWithRenderTexture(Texture texture, out Color color)
		{
			//IL_0001: 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_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			color = default(Color);
			RenderTexture active = RenderTexture.active;
			RenderTexture val = null;
			Texture2D val2 = null;
			try
			{
				val = RenderTexture.GetTemporary(16, 16, 0, (RenderTextureFormat)0);
				val2 = new Texture2D(16, 16, (TextureFormat)4, false);
				Graphics.Blit(texture, val);
				RenderTexture.active = val;
				val2.ReadPixels(new Rect(0f, 0f, 16f, 16f), 0, 0);
				val2.Apply(false, false);
				return TryAverageReadableTexturePixels(val2, out color);
			}
			catch
			{
				color = default(Color);
				return false;
			}
			finally
			{
				RenderTexture.active = active;
				if ((Object)(object)val != (Object)null)
				{
					RenderTexture.ReleaseTemporary(val);
				}
				if ((Object)(object)val2 != (Object)null)
				{
					Object.Destroy((Object)(object)val2);
				}
			}
		}

		private static bool TryAverageReadableTexturePixels(Texture2D texture, out Color color)
		{
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: 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_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			float num = 0f;
			float num2 = 0f;
			float num3 = 0f;
			float num4 = 0f;
			for (int i = 0; i < 16; i++)
			{
				for (int j = 0; j < 16; j++)
				{
					Color pixelBilinear = texture.GetPixelBilinear(((float)j + 0.5f) / 16f, ((float)i + 0.5f) / 16f);
					float num5 = Mathf.Clamp01(pixelBilinear.a);
					if (!(num5 < 0.08f))
					{
						num2 += pixelBilinear.r * num5;
						num3 += pixelBilinear.g * num5;
						num4 += pixelBilinear.b * num5;
						num += num5;
					}
				}
			}
			if (num <= 0.001f)
			{
				color = default(Color);
				return false;
			}
			color = NormalizePaintColor(new Color(num2 / num, num3 / num, num4 / num, 1f));
			return true;
		}

		private static Color NormalizePaintColor(Color color)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: 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_0045: 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)
			color.r = Mathf.Clamp01(color.r);
			color.g = Mathf.Clamp01(color.g);
			color.b = Mathf.Clamp01(color.b);
			color.a = ((color.a < 0.2f) ? 1f : Mathf.Clamp01(color.a));
			return color;
		}

		private static bool IsUsefulPaintColor(Color color)
		{
			//IL_0000: 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_000c: 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_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)
			float num = Mathf.Max(color.r, Mathf.Max(color.g, color.b));
			float num2 = Mathf.Min(color.r, Mathf.Min(color.g, color.b));
			float num3 = ((num <= 0.001f) ? 0f : ((num - num2) / num));
			if (num > 0.05f)
			{
				if (num > 0.92f)
				{
					return !(num3 < 0.08f);
				}
				return true;
			}
			return false;
		}

		private static Color LogResolvedColor(SprayPaintItem sprayPaintItem, Color color, int colorIndex, string source)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//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_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			Color val = NormalizePaintColor(color);
			if (Plugin.ModConfig.EnableDebugLogging.Value)
			{
				Plugin.Log.LogInfo((object)("Resolved spray paint color " + ColorUtility.ToHtmlStringRGBA(val) + " from " + source + "; " + string.Format("sprayCanMatsIndex={0}, {1}, {2}.", colorIndex, DescribeSelectedMaterial(sprayPaintItem, "particleMats", colorIndex), DescribeSelectedMaterial(sprayPaintItem, "sprayCanMats", colorIndex))));
			}
			return val;
		}

		private static string DescribeSelectedMaterial(SprayPaintItem sprayPaintItem, string fieldName, int colorIndex)
		{
			Material[] objectField = GetObjectField<Material[]>(sprayPaintItem, new string[1] { fieldName });
			if (objectField == null)
			{
				return fieldName + "=missing";
			}
			if (colorIndex < 0 || colorIndex >= objectField.Length)
			{
				return $"{fieldName}=index {colorIndex} outside {objectField.Length}";
			}
			Material val = objectField[colorIndex];
			if (!((Object)(object)val == (Object)null))
			{
				return $"{fieldName}[{colorIndex}]={((Object)val).name}";
			}
			return $"{fieldName}[{colorIndex}]=null";
		}

		private static object? GetDefaultValue(Type type)
		{
			if (!type.IsValueType)
			{
				return null;
			}
			return Activator.CreateInstance(type);
		}
	}
	internal static class SprayPaintRuntimeWatcher
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static LogCallback <0>__OnUnityLogMessageReceived;
		}

		private static SprayPaintItem? _lastSprayPaintItem;

		private static int _lastInstanceId;

		private static float _lastShakeMeter = -1f;

		private static bool _lastIsSpraying;

		private static float _nextDebugLogTime;

		private static float _lastLogFallbackTriggerTime = -10f;

		private static bool _registered;

		internal static void Register()
		{
			//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_0023: Expected O, but got Unknown
			if (!_registered)
			{
				object obj = <>O.<0>__OnUnityLogMessageReceived;
				if (obj == null)
				{
					LogCallback val = OnUnityLogMessageReceived;
					<>O.<0>__OnUnityLogMessageReceived = val;
					obj = (object)val;
				}
				Application.logMessageReceived += (LogCallback)obj;
				_registered = true;
				LogDebug("Runtime watcher registered on plugin update loop and Unity log fallback.");
			}
		}

		internal static void Unregister()
		{
			//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_0023: Expected O, but got Unknown
			if (_registered)
			{
				object obj = <>O.<0>__OnUnityLogMessageReceived;
				if (obj == null)
				{
					LogCallback val = OnUnityLogMessageReceived;
					<>O.<0>__OnUnityLogMessageReceived = val;
					obj = (object)val;
				}
				Application.logMessageReceived -= (LogCallback)obj;
				_registered = false;
				LogDebug("Runtime watcher unregistered.");
			}
		}

		internal static void Tick()
		{
			PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController;
			SprayPaintItem val2 = SprayPaintItemPatches.FindLocalHeldSprayPaint();
			if ((Object)(object)val2 == (Object)null)
			{
				ClearHeldItem();
				return;
			}
			int instanceID = ((Object)val2).GetInstanceID();
			float valueOrDefault = SprayPaintIntrospection.GetFloatField(val2, "sprayCanShakeMeter").GetValueOrDefault(-1f);
			bool valueOrDefault2 = SprayPaintIntrospection.GetBoolField(val2, "isSpraying").GetValueOrDefault();
			if ((Object)(object)_lastSprayPaintItem != (Object)(object)val2 || _lastInstanceId != instanceID)
			{
				_lastSprayPaintItem = val2;
				_lastInstanceId = instanceID;
				_lastShakeMeter = valueOrDefault;
				_lastIsSpraying = valueOrDefault2;
				object[] obj = new object[4] { instanceID, null, null, null };
				NetworkObject networkObject = ((NetworkBehaviour)val2).NetworkObject;
				obj[1] = ((networkObject != null) ? networkObject.NetworkObjectId.ToString() : null) ?? "none";
				obj[2] = valueOrDefault;
				obj[3] = valueOrDefault2;
				LogDebug(string.Format("Runtime watcher tracking held SprayPaintItem. instance={0}, objectId={1}, shakeMeter={2:0.00}, isSpraying={3}.", obj));
				return;
			}
			if (valueOrDefault >= 0f && _lastShakeMeter >= 0f && valueOrDefault - _lastShakeMeter >= 0.03f)
			{
				SprayPaintItemPatches.ReportShake(val2, $"runtime watcher shake meter {_lastShakeMeter:0.00}->{valueOrDefault:0.00}");
			}
			if (Plugin.ModConfig.EnableDebugLogging.Value && Time.unscaledTime >= _nextDebugLogTime)
			{
				_nextDebugLogTime = Time.unscaledTime + 5f;
				object[] obj2 = new object[5] { instanceID, null, null, null, null };
				NetworkObject networkObject2 = ((NetworkBehaviour)val2).NetworkObject;
				obj2[1] = ((networkObject2 != null) ? networkObject2.NetworkObjectId.ToString() : null) ?? "none";
				obj2[2] = valueOrDefault;
				obj2[3] = valueOrDefault2;
				obj2[4] = (Object)(object)((GrabbableObject)val2).playerHeldBy == (Object)(object)val;
				LogDebug(string.Format("Runtime watcher heartbeat. instance={0}, objectId={1}, shakeMeter={2:0.00}, isSpraying={3}, heldByLocal={4}.", obj2));
			}
			_lastShakeMeter = valueOrDefault;
			_lastIsSpraying = valueOrDefault2;
		}

		private static void OnUnityLogMessageReceived(string condition, string stackTrace, LogType type)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Invalid comparison between Unknown and I4
			if ((int)type == 3 && (condition.StartsWith("interact False") || condition == "secondary use G") && !(Time.unscaledTime - _lastLogFallbackTriggerTime < 0.25f))
			{
				_lastLogFallbackTriggerTime = Time.unscaledTime;
				SprayPaintItem val = SprayPaintItemPatches.FindLocalHeldSprayPaint();
				if ((Object)(object)val == (Object)null)
				{
					LogDebug("Unity log fallback saw '" + condition + "', but could not find a locally held SprayPaintItem.");
				}
				else
				{
					SprayPaintItemPatches.ReportShake(val, "Unity log fallback '" + condition + "'");
				}
			}
		}

		private static void ClearHeldItem()
		{
			if ((Object)(object)_lastSprayPaintItem != (Object)null)
			{
				LogDebug("Runtime watcher stopped tracking SprayPaintItem because the local player is no longer holding one.");
			}
			_lastSprayPaintItem = null;
			_lastInstanceId = 0;
			_lastShakeMeter = -1f;
			_lastIsSpraying = false;
		}

		private static void LogDebug(string message)
		{
			if (Plugin.ModConfig.EnableDebugLogging.Value)
			{
				Plugin.Log.LogInfo((object)message);
			}
		}
	}
	internal sealed class TemporaryObject : MonoBehaviour
	{
		private bool _destroyInstancedMaterials;

		internal void Initialize(float lifetimeSeconds, bool destroyInstancedMaterials)
		{
			_destroyInstancedMaterials = destroyInstancedMaterials;
			((MonoBehaviour)this).StartCoroutine(DestroyAfterDelay(lifetimeSeconds));
		}

		private IEnumerator DestroyAfterDelay(float lifetimeSeconds)
		{
			yield return (object)new WaitForSeconds(lifetimeSeconds);
			if ((Object)(object)this != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)this).gameObject);
			}
		}

		private void OnDestroy()
		{
			if (!_destroyInstancedMaterials)
			{
				return;
			}
			Renderer[] componentsInChildren = ((Component)this).GetComponentsInChildren<Renderer>();
			foreach (Renderer val in componentsInChildren)
			{
				if ((Object)(object)val.material != (Object)null)
				{
					Texture mainTexture = val.material.mainTexture;
					if ((Object)(object)mainTexture != (Object)null && ((Object)mainTexture).name.StartsWith("ExplosiveSprayPaint_"))
					{
						Object.Destroy((Object)(object)mainTexture);
					}
					Object.Destroy((Object)(object)val.material);
				}
			}
			DecalProjector[] componentsInChildren2 = ((Component)this).GetComponentsInChildren<DecalProjector>();
			foreach (DecalProjector val2 in componentsInChildren2)
			{
				if ((Object)(object)val2.material != (Object)null)
				{
					Object.Destroy((Object)(object)val2.material);
				}
			}
		}
	}
}
namespace ExplosiveSprayPaint.Patches
{
	internal static class NetworkLifecyclePatches
	{
		[HarmonyPatch(typeof(PlayerControllerB), "ConnectClientToPlayerObject")]
		[HarmonyPostfix]
		private static void RegisterMessagesAfterConnect()
		{
			SprayCanExplosionNetworking.Register();
		}

		[HarmonyPatch(typeof(StartOfRound), "Awake")]
		[HarmonyPostfix]
		private static void ClearRoundStateOnStart()
		{
			ExplosionState.Reset();
		}
	}
	internal static class SprayPaintItemPatches
	{
		internal const float ShakeMeterIncreaseThreshold = 0.03f;

		internal static void Apply(Harmony harmony)
		{
			Patch(harmony, "ItemInteractLeftRight", null, "DetectShake");
			Patch(harmony, "ItemActivate", null, "DetectOptionalSprayUse");
			Patch(harmony, "LateUpdate", "CaptureShakeMeterBeforeLateUpdate", "DetectShakeMeterIncrease");
			Patch(harmony, "Start", null, "LogSprayPaintStart");
			Patch(harmony, typeof(PlayerControllerB), "Update", null, "TickRuntimeWatcherFromPlayerUpdate");
		}

		private static void Patch(Harmony harmony, string originalName, string? prefixName = null, string? postfixName = null)
		{
			Patch(harmony, typeof(SprayPaintItem), originalName, prefixName, postfixName);
		}

		private static void Patch(Harmony harmony, Type originalType, string originalName, string? prefixName = null, string? postfixName = null)
		{
			//IL_0063: 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)
			MethodInfo methodInfo = AccessTools.Method(originalType, originalName, (Type[])null, (Type[])null);
			if (methodInfo == null)
			{
				Plugin.Log.LogError((object)("Could not find " + originalType.Name + "." + originalName + "; this mod cannot detect that action."));
				return;
			}
			HarmonyMethod val = ((prefixName == null) ? ((HarmonyMethod)null) : new HarmonyMethod(AccessTools.Method(typeof(SprayPaintItemPatches), prefixName, (Type[])null, (Type[])null)));
			HarmonyMethod val2 = ((postfixName == null) ? ((HarmonyMethod)null) : new HarmonyMethod(AccessTools.Method(typeof(SprayPaintItemPatches), postfixName, (Type[])null, (Type[])null)));
			harmony.Patch((MethodBase)methodInfo, val, val2, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			Patches patchInfo = Harmony.GetPatchInfo((MethodBase)methodInfo);
			int num = patchInfo?.Prefixes.Count((Patch patch) => patch.owner == "huntedbyacreature.explosivespraypaint") ?? 0;
			int num2 = patchInfo?.Postfixes.Count((Patch patch) => patch.owner == "huntedbyacreature.explosivespraypaint") ?? 0;
			Plugin.Log.LogInfo((object)$"Patch check: {originalType.Name}.{originalName} prefixes={num}, postfixes={num2}.");
		}

		private static void DetectShake(SprayPaintItem __instance, bool right)
		{
			if (!right)
			{
				ReportShake(__instance, "ItemInteractLeftRight(false)");
			}
		}

		private static void DetectOptionalSprayUse(SprayPaintItem __instance, bool used, bool buttonDown)
		{
			LogDebug($"ItemActivate observed. used={used}, buttonDown={buttonDown}; spraying is safe and does not roll explosions.");
		}

		private static void CaptureShakeMeterBeforeLateUpdate(SprayPaintItem __instance, out float __state)
		{
			__state = SprayPaintIntrospection.GetFloatField(__instance, "sprayCanShakeMeter").GetValueOrDefault(-1f);
		}

		private static void DetectShakeMeterIncrease(SprayPaintItem __instance, float __state)
		{
			if (!(__state < 0f))
			{
				float valueOrDefault = SprayPaintIntrospection.GetFloatField(__instance, "sprayCanShakeMeter").GetValueOrDefault(__state);
				if (valueOrDefault - __state >= 0.03f)
				{
					ReportShake(__instance, $"sprayCanShakeMeter increased {__state:0.00}->{valueOrDefault:0.00}");
				}
			}
		}

		private static void LogSprayPaintStart(SprayPaintItem __instance)
		{
			NetworkObject networkObject = ((NetworkBehaviour)__instance).NetworkObject;
			LogDebug("SprayPaintItem started. objectId=" + (((networkObject != null) ? networkObject.NetworkObjectId.ToString() : null) ?? "none") + ", shakeMeter=" + (SprayPaintIntrospection.GetFloatField(__instance, "sprayCanShakeMeter")?.ToString("0.00") ?? "unknown"));
		}

		private static void TickRuntimeWatcherFromPlayerUpdate()
		{
			SprayPaintRuntimeWatcher.Tick();
		}

		internal static void ReportShake(SprayPaintItem sprayPaintItem, string source)
		{
			if ((Object)(object)sprayPaintItem == (Object)null || (Object)(object)((GrabbableObject)sprayPaintItem).playerHeldBy == (Object)null)
			{
				LogDebug("Ignoring " + source + " because the spray can is not held.");
				return;
			}
			if (SprayPaintIntrospection.GetBoolField(sprayPaintItem, "isSpraying").GetValueOrDefault())
			{
				LogDebug("Ignoring " + source + " because the can is actively spraying. Spraying paint is safe; only shaking can rupture it.");
				return;
			}
			if (!IsHeldByLocalPlayer(((GrabbableObject)sprayPaintItem).playerHeldBy))
			{
				object arg = ((GrabbableObject)sprayPaintItem).playerHeldBy.actualClientId;
				NetworkManager singleton = NetworkManager.Singleton;
				LogDebug(string.Format("Ignoring {0} because the holder is not the local player. holder={1}, local={2}.", source, arg, ((singleton != null) ? singleton.LocalClientId.ToString() : null) ?? "none"));
				return;
			}
			string[] obj = new string[6]
			{
				"Detected local spray can shake via ",
				source,
				". holder=",
				((GrabbableObject)sprayPaintItem).playerHeldBy.playerUsername,
				", objectId=",
				null
			};
			NetworkObject networkObject = ((NetworkBehaviour)sprayPaintItem).NetworkObject;
			obj[5] = ((networkObject != null) ? networkObject.NetworkObjectId.ToString() : null) ?? "none";
			LogDebug(string.Concat(obj));
			SprayCanExplosionNetworking.ReportLocalShake(sprayPaintItem);
		}

		internal static SprayPaintItem? FindLocalHeldSprayPaint()
		{
			PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController;
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			GrabbableObject currentlyHeldObjectServer = val.currentlyHeldObjectServer;
			SprayPaintItem val2 = (SprayPaintItem)(object)((currentlyHeldObjectServer is SprayPaintItem) ? currentlyHeldObjectServer : null);
			if (val2 != null)
			{
				return val2;
			}
			SprayPaintItem[] array = Object.FindObjectsOfType<SprayPaintItem>();
			foreach (SprayPaintItem val3 in array)
			{
				if (!((Object)(object)val3 == (Object)null) && !((Object)(object)((GrabbableObject)val3).playerHeldBy == (Object)null) && ((Object)(object)((GrabbableObject)val3).playerHeldBy == (Object)(object)val || IsHeldByLocalPlayer(((GrabbableObject)val3).playerHeldBy)))
				{
					return val3;
				}
			}
			return null;
		}

		internal static bool IsHeldByLocalPlayer(PlayerControllerB holder)
		{
			PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController;
			if ((Object)(object)val != (Object)null && (Object)(object)holder == (Object)(object)val)
			{
				return true;
			}
			NetworkManager singleton = NetworkManager.Singleton;
			if ((Object)(object)singleton != (Object)null && singleton.IsListening)
			{
				return holder.actualClientId == singleton.LocalClientId;
			}
			return ((NetworkBehaviour)holder).IsOwner;
		}

		internal static void LogDebug(string message)
		{
			if (Plugin.ModConfig.EnableDebugLogging.Value)
			{
				Plugin.Log.LogInfo((object)message);
			}
		}
	}
}
namespace ExplosiveSprayPaint.Networking
{
	internal readonly struct ExplosionMessage
	{
		internal readonly ulong SprayCanNetworkObjectId;

		internal readonly ulong HolderClientId;

		internal readonly Vector3 Position;

		internal readonly Color PaintColor;

		internal readonly bool Catastrophic;

		internal readonly int RandomSeed;

		internal readonly float BlastRadius;

		internal readonly float PhysicsForce;

		internal readonly float PaintRadius;

		internal readonly int PaintCount;

		internal ExplosionMessage(ulong sprayCanNetworkObjectId, ulong holderClientId, Vector3 position, Color paintColor, bool catastrophic, int randomSeed, float blastRadius, float physicsForce, float paintRadius, int paintCount)
		{
			//IL_000f: 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_0016: 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)
			SprayCanNetworkObjectId = sprayCanNetworkObjectId;
			HolderClientId = holderClientId;
			Position = position;
			PaintColor = paintColor;
			Catastrophic = catastrophic;
			RandomSeed = randomSeed;
			BlastRadius = blastRadius;
			PhysicsForce = physicsForce;
			PaintRadius = paintRadius;
			PaintCount = paintCount;
		}

		internal void Write(FastBufferWriter writer)
		{
			//IL_000a: 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_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: 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_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: 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_0071: 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_008c: 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_00a7: 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_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: 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_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: 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)
			((FastBufferWriter)(ref writer)).WriteValueSafe<ulong>(ref SprayCanNetworkObjectId, default(ForPrimitives));
			((FastBufferWriter)(ref writer)).WriteValueSafe<ulong>(ref HolderClientId, default(ForPrimitives));
			((FastBufferWriter)(ref writer)).WriteValueSafe<float>(ref Position.x, default(ForPrimitives));
			((FastBufferWriter)(ref writer)).WriteValueSafe<float>(ref Position.y, default(ForPrimitives));
			((FastBufferWriter)(ref writer)).WriteValueSafe<float>(ref Position.z, default(ForPrimitives));
			((FastBufferWriter)(ref writer)).WriteValueSafe<float>(ref PaintColor.r, default(ForPrimitives));
			((FastBufferWriter)(ref writer)).WriteValueSafe<float>(ref PaintColor.g, default(ForPrimitives));
			((FastBufferWriter)(ref writer)).WriteValueSafe<float>(ref PaintColor.b, default(ForPrimitives));
			((FastBufferWriter)(ref writer)).WriteValueSafe<float>(ref PaintColor.a, default(ForPrimitives));
			((FastBufferWriter)(ref writer)).WriteValueSafe<bool>(ref Catastrophic, default(ForPrimitives));
			((FastBufferWriter)(ref writer)).WriteValueSafe<int>(ref RandomSeed, default(ForPrimitives));
			((FastBufferWriter)(ref writer)).WriteValueSafe<float>(ref BlastRadius, default(ForPrimitives));
			((FastBufferWriter)(ref writer)).WriteValueSafe<float>(ref PhysicsForce, default(ForPrimitives));
			((FastBufferWriter)(ref writer)).WriteValueSafe<float>(ref PaintRadius, default(ForPrimitives));
			((FastBufferWriter)(ref writer)).WriteValueSafe<int>(ref PaintCount, default(ForPrimitives));
		}

		internal static bool TryRead(FastBufferReader reader, out ExplosionMessage message)
		{
			//IL_000d: 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_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: 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_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: 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_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: 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_0085: 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_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)
			//IL_00b8: 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_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: 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_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			message = default(ExplosionMessage);
			try
			{
				ulong sprayCanNetworkObjectId = default(ulong);
				((FastBufferReader)(ref reader)).ReadValueSafe<ulong>(ref sprayCanNetworkObjectId, default(ForPrimitives));
				ulong holderClientId = default(ulong);
				((FastBufferReader)(ref reader)).ReadValueSafe<ulong>(ref holderClientId, default(ForPrimitives));
				float num = default(float);
				((FastBufferReader)(ref reader)).ReadValueSafe<float>(ref num, default(ForPrimitives));
				float num2 = default(float);
				((FastBufferReader)(ref reader)).ReadValueSafe<float>(ref num2, default(ForPrimitives));
				float num3 = default(float);
				((FastBufferReader)(ref reader)).ReadValueSafe<float>(ref num3, default(ForPrimitives));
				float num4 = default(float);
				((FastBufferReader)(ref reader)).ReadValueSafe<float>(ref num4, default(ForPrimitives));
				float num5 = default(float);
				((FastBufferReader)(ref reader)).ReadValueSafe<float>(ref num5, default(ForPrimitives));
				float num6 = default(float);
				((FastBufferReader)(ref reader)).ReadValueSafe<float>(ref num6, default(ForPrimitives));
				float num7 = default(float);
				((FastBufferReader)(ref reader)).ReadValueSafe<float>(ref num7, default(ForPrimitives));
				bool catastrophic = default(bool);
				((FastBufferReader)(ref reader)).ReadValueSafe<bool>(ref catastrophic, default(ForPrimitives));
				int randomSeed = default(int);
				((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref randomSeed, default(ForPrimitives));
				float blastRadius = default(float);
				((FastBufferReader)(ref reader)).ReadValueSafe<float>(ref blastRadius, default(ForPrimitives));
				float physicsForce = default(float);
				((FastBufferReader)(ref reader)).ReadValueSafe<float>(ref physicsForce, default(ForPrimitives));
				float paintRadius = default(float);
				((FastBufferReader)(ref reader)).ReadValueSafe<float>(ref paintRadius, default(ForPrimitives));
				int paintCount = default(int);
				((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref paintCount, default(ForPrimitives));
				message = new ExplosionMessage(sprayCanNetworkObjectId, holderClientId, new Vector3(num, num2, num3), new Color(num4, num5, num6, num7), catastrophic, randomSeed, blastRadius, physicsForce, paintRadius, paintCount);
				return true;
			}
			catch (Exception arg)
			{
				Plugin.Log.LogWarning((object)$"Failed to read explosion message: {arg}");
				return false;
			}
		}
	}
	internal static class ExplosionState
	{
		private static readonly HashSet<ulong> ExplodedNetworkObjects = new HashSet<ulong>();

		private static readonly Dictionary<ulong, int> LastShakeRequestFrame = new Dictionary<ulong, int>();

		internal static bool HasExploded(ulong networkObjectId)
		{
			lock (ExplodedNetworkObjects)
			{
				return ExplodedNetworkObjects.Contains(networkObjectId);
			}
		}

		internal static bool TryMarkExploded(ulong networkObjectId)
		{
			lock (ExplodedNetworkObjects)
			{
				return ExplodedNetworkObjects.Add(networkObjectId);
			}
		}

		internal static bool TryMarkShakeRequestThisFrame(ulong networkObjectId, int frame)
		{
			lock (LastShakeRequestFrame)
			{
				if (LastShakeRequestFrame.TryGetValue(networkObjectId, out var value) && value == frame)
				{
					return false;
				}
				LastShakeRequestFrame[networkObjectId] = frame;
				return true;
			}
		}

		internal static void Reset()
		{
			lock (ExplodedNetworkObjects)
			{
				ExplodedNetworkObjects.Clear();
			}
			lock (LastShakeRequestFrame)
			{
				LastShakeRequestFrame.Clear();
			}
		}
	}
	internal static class SprayCanExplosionNetworking
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static HandleNamedMessageDelegate <0>__OnShakeRequestReceived;

			public static HandleNamedMessageDelegate <1>__OnExplosionReceived;
		}

		private const string ShakeRequestMessage = "huntedbyacreature.explosivespraypaint.ShakeRequest";

		private const string ExplosionMessageName = "huntedbyacreature.explosivespraypaint.Explosion";

		private static bool _registered;

		internal static void Register()
		{
			//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_0042: Expected O, but got Unknown
			//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)
			//IL_006d: Expected O, but got Unknown
			NetworkManager singleton = NetworkManager.Singleton;
			if (!_registered && ((singleton != null) ? singleton.CustomMessagingManager : null) != null)
			{
				CustomMessagingManager customMessagingManager = singleton.CustomMessagingManager;
				object obj = <>O.<0>__OnShakeRequestReceived;
				if (obj == null)
				{
					HandleNamedMessageDelegate val = OnShakeRequestReceived;
					<>O.<0>__OnShakeRequestReceived = val;
					obj = (object)val;
				}
				customMessagingManager.RegisterNamedMessageHandler("huntedbyacreature.explosivespraypaint.ShakeRequest", (HandleNamedMessageDelegate)obj);
				CustomMessagingManager customMessagingManager2 = singleton.CustomMessagingManager;
				object obj2 = <>O.<1>__OnExplosionReceived;
				if (obj2 == null)
				{
					HandleNamedMessageDelegate val2 = OnExplosionReceived;
					<>O.<1>__OnExplosionReceived = val2;
					obj2 = (object)val2;
				}
				customMessagingManager2.RegisterNamedMessageHandler("huntedbyacreature.explosivespraypaint.Explosion", (HandleNamedMessageDelegate)obj2);
				_registered = true;
			}
		}

		internal static void Unregister()
		{
			NetworkManager singleton = NetworkManager.Singleton;
			if (_registered && ((singleton != null) ? singleton.CustomMessagingManager : null) != null)
			{
				singleton.CustomMessagingManager.UnregisterNamedMessageHandler("huntedbyacreature.explosivespraypaint.ShakeRequest");
				singleton.CustomMessagingManager.UnregisterNamedMessageHandler("huntedbyacreature.explosivespraypaint.Explosion");
				_registered = false;
			}
		}

		internal static void ReportLocalShake(SprayPaintItem sprayPaintItem)
		{
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			Register();
			NetworkObject networkObject = ((NetworkBehaviour)sprayPaintItem).NetworkObject;
			if ((Object)(object)networkObject == (Object)null || ExplosionState.HasExploded(networkObject.NetworkObjectId))
			{
				LogDebug(((Object)(object)networkObject == (Object)null) ? "Shake ignored because the spray can has no NetworkObject." : $"Shake ignored because spray can {networkObject.NetworkObjectId} already exploded.");
				return;
			}
			if (!ExplosionState.TryMarkShakeRequestThisFrame(networkObject.NetworkObjectId, Time.frameCount))
			{
				LogDebug($"Duplicate shake request ignored for frame {Time.frameCount}, object {networkObject.NetworkObjectId}.");
				return;
			}
			NetworkManager singleton = NetworkManager.Singleton;
			if ((Object)(object)singleton == (Object)null || !singleton.IsListening)
			{
				LogDebug("Shake detected, but NetworkManager is not listening yet.");
				return;
			}
			if (singleton.IsServer)
			{
				LogDebug($"Processing shake locally on host for object {networkObject.NetworkObjectId}.");
				TryProcessShakeOnServer(sprayPaintItem, singleton.LocalClientId);
				return;
			}
			LogDebug($"Sending shake request to host for object {networkObject.NetworkObjectId}.");
			FastBufferWriter val = default(FastBufferWriter);
			((FastBufferWriter)(ref val))..ctor(8, (Allocator)2, -1);
			try
			{
				ulong networkObjectId = networkObject.NetworkObjectId;
				((FastBufferWriter)(ref val)).WriteValueSafe<ulong>(ref networkObjectId, default(ForPrimitives));
				singleton.CustomMessagingManager.SendNamedMessage("huntedbyacreature.explosivespraypaint.ShakeRequest", 0uL, val, (NetworkDelivery)2);
			}
			finally
			{
				((IDisposable)(FastBufferWriter)(ref val)).Dispose();
			}
		}

		private static void OnShakeRequestReceived(ulong senderClientId, FastBufferReader reader)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager singleton = NetworkManager.Singleton;
			if (!((Object)(object)singleton == (Object)null) && singleton.IsServer)
			{
				ulong num = default(ulong);
				((FastBufferReader)(ref reader)).ReadValueSafe<ulong>(ref num, default(ForPrimitives));
				LogDebug($"Host received shake request from client {senderClientId} for object {num}.");
				SprayPaintItem sprayPaintItem = default(SprayPaintItem);
				if (!singleton.SpawnManager.SpawnedObjects.TryGetValue(num, out var value))
				{
					LogDebug($"Host could not find spawned object {num}.");
				}
				else if (!((Component)value).TryGetComponent<SprayPaintItem>(ref sprayPaintItem))
				{
					LogDebug($"Host object {num} is not a SprayPaintItem.");
				}
				else
				{
					TryProcessShakeOnServer(sprayPaintItem, senderClientId);
				}
			}
		}

		private static void TryProcessShakeOnServer(SprayPaintItem sprayPaintItem, ulong senderClientId)
		{
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01db: Unknown result type (might be due to invalid IL or missing references)
			NetworkObject networkObject = ((NetworkBehaviour)sprayPaintItem).NetworkObject;
			if ((Object)(object)networkObject == (Object)null || ExplosionState.HasExploded(networkObject.NetworkObjectId))
			{
				LogDebug(((Object)(object)networkObject == (Object)null) ? "Host ignored shake because the spray can has no NetworkObject." : $"Host ignored shake because object {networkObject.NetworkObjectId}