Decompiled source of FireSalts v0.1.1

BepInEx/plugins/FireSalts/FireSalts.dll

Decompiled 12 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: InternalsVisibleTo("FireSalts.RuntimeProbe")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("FireSalts")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.1.1.0")]
[assembly: AssemblyInformationalVersion("0.1.1")]
[assembly: AssemblyProduct("FireSalts")]
[assembly: AssemblyTitle("FireSalts")]
[assembly: AssemblyVersion("0.1.1.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace FireSalts
{
	internal sealed class FireRuntime : MonoBehaviour
	{
		internal static readonly List<FireRuntime> Live = new List<FireRuntime>();

		private static readonly List<FireRuntime> nearest = new List<FireRuntime>();

		private static readonly Collider[] overlaps = (Collider[])(object)new Collider[32];

		private static readonly HashSet<ItemDrop> visited = new HashSet<ItemDrop>();

		private static int cursor;

		internal Fireplace Fire;

		internal ZNetView View;

		internal string Prefab;

		internal FireVisual Visual;

		private bool selected;

		private float distance;

		internal bool Valid
		{
			get
			{
				if ((Object)(object)Fire != (Object)null && (Object)(object)View != (Object)null)
				{
					return View.IsValid();
				}
				return false;
			}
		}

		internal bool Burning
		{
			get
			{
				if (Valid)
				{
					return Fire.IsBurning();
				}
				return false;
			}
		}

		internal Vector3 Center => ((Component)this).transform.TransformPoint(Vector3.up * ((Prefab == "bonfire") ? 1.1f : 0.5f));

		internal static void Attach(Fireplace fire)
		{
			ZNetView component = ((Component)fire).GetComponent<ZNetView>();
			if ((Object)(object)component == (Object)null || !component.IsValid() || (Object)(object)((Component)fire).GetComponent<FireRuntime>() != (Object)null)
			{
				return;
			}
			string text = null;
			string[] array = new string[3] { "fire_pit", "hearth", "bonfire" };
			foreach (string text2 in array)
			{
				if (component.GetZDO().GetPrefab() == StringExtensionMethods.GetStableHashCode(text2))
				{
					text = text2;
				}
			}
			if (text != null)
			{
				FireRuntime fireRuntime = ((Component)fire).gameObject.AddComponent<FireRuntime>();
				fireRuntime.Fire = fire;
				fireRuntime.View = component;
				fireRuntime.Prefab = text;
				Live.Add(fireRuntime);
			}
		}

		private void OnDestroy()
		{
			Restore();
			Live.Remove(this);
		}

		private void OnDisable()
		{
			Restore();
		}

		internal bool Active(long now, out int salt, out long start)
		{
			salt = 0;
			start = 0L;
			if (Valid)
			{
				return Rules.TryState(View.GetZDO().GetString("smeagsmods.firesalts.state.v1", ""), now, out salt, out start);
			}
			return false;
		}

		internal bool Contains(Vector3 world)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = ((Component)this).transform.InverseTransformPoint(world);
			return Rules.InVolume(Prefab, val.x, val.y, val.z);
		}

		internal static void TickAuthority()
		{
			if (!Plugin.Running || (Object)(object)ZNet.instance == (Object)null || Live.Count == 0)
			{
				return;
			}
			long now = Plugin.Now;
			int num = Math.Min(Live.Count, 16);
			for (int i = 0; i < num; i++)
			{
				if (cursor >= Live.Count)
				{
					cursor = 0;
				}
				FireRuntime fireRuntime = Live[cursor++];
				if ((Object)(object)fireRuntime != (Object)null && fireRuntime.Valid && fireRuntime.View.IsOwner())
				{
					fireRuntime.Scan(now);
				}
			}
		}

		private void Scan(long now)
		{
			//IL_00ca: 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_00d6: 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_009e: 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_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: 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_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0226: Unknown result type (might be due to invalid IL or missing references)
			//IL_0282: Unknown result type (might be due to invalid IL or missing references)
			ZDO zdo = View.GetZDO();
			int salt;
			long start;
			bool flag = Active(now, out salt, out start);
			bool burning = Burning;
			if ((!flag || !burning) && zdo.GetString("smeagsmods.firesalts.state.v1", "").Length > 0)
			{
				zdo.Set("smeagsmods.firesalts.state.v1", "");
			}
			if (!burning || flag)
			{
				return;
			}
			Vector3 val = ((Prefab == "bonfire") ? new Vector3(1.2f, 1.4f, 1.2f) : ((Prefab == "hearth") ? new Vector3(0.85f, 0.7f, 1.4f) : new Vector3(0.8f, 0.65f, 0.8f)));
			int num = Physics.OverlapBoxNonAlloc(((Component)this).transform.TransformPoint(Vector3.up * ((Prefab == "bonfire") ? 1.5f : 0.65f)), val, overlaps, ((Component)this).transform.rotation, LayerMask.GetMask(new string[1] { "item" }), (QueryTriggerInteraction)1);
			visited.Clear();
			for (int i = 0; i < num; i++)
			{
				Collider val2 = overlaps[i];
				overlaps[i] = null;
				if ((Object)(object)val2 == (Object)null || (Object)(object)val2.attachedRigidbody == (Object)null)
				{
					continue;
				}
				ItemDrop component = ((Component)val2.attachedRigidbody).GetComponent<ItemDrop>();
				if ((Object)(object)component == (Object)null || !visited.Add(component))
				{
					continue;
				}
				Salt salt2 = Salts.Get(component);
				ZNetView component2 = ((Component)component).GetComponent<ZNetView>();
				if (salt2 == null || (Object)(object)component2 == (Object)null || !component2.IsValid() || !Contains(((Component)component).transform.position))
				{
					continue;
				}
				ZDO data = component2.GetZDO();
				long num2 = data.GetLong("smeagsmods.firesalts.armed.v1", 0L);
				if (!Rules.IsArmed(num2, now) || (Object)(object)NearestContaining(((Component)component).transform.position) != (Object)(object)this)
				{
					continue;
				}
				if (!component2.IsOwner())
				{
					component.RequestOwn();
					continue;
				}
				component.Load();
				if (Rules.CanConsume(View.IsOwner(), component2.IsOwner(), Burning, Active(now, out salt, out start), Contains(((Component)component).transform.position), component.m_itemData.m_stack, salt2.Id, data.GetLong("smeagsmods.firesalts.armed.v1", 0L), now) && component.CanPickup(true) && Reaction.Apply(salt2.Id, now, num2, (Action<long>)delegate(long value)
				{
					data.Set("smeagsmods.firesalts.armed.v1", value);
				}, (Func<bool>)component.RemoveOne, (Action<string>)delegate(string state)
				{
					zdo.Set("smeagsmods.firesalts.state.v1", state);
				}))
				{
					Plugin.Log("Consumed one " + salt2.Prefab + " at " + Prefab + "; shared deadline " + Rules.Expiry(now, 30));
					break;
				}
			}
		}

		private static FireRuntime NearestContaining(Vector3 position)
		{
			//IL_0032: 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_0040: 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)
			FireRuntime fireRuntime = null;
			float num = float.MaxValue;
			foreach (FireRuntime item in Live)
			{
				if (!((Object)(object)item == (Object)null) && item.Burning && item.Contains(position))
				{
					Vector3 val = item.Center - position;
					float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude;
					if (sqrMagnitude < num || (sqrMagnitude == num && (Object)(object)fireRuntime != (Object)null && string.CompareOrdinal(((object)Unsafe.As<ZDOID, ZDOID>(ref item.View.GetZDO().m_uid)/*cast due to .constrained prefix*/).ToString(), ((object)Unsafe.As<ZDOID, ZDOID>(ref fireRuntime.View.GetZDO().m_uid)/*cast due to .constrained prefix*/).ToString()) < 0))
					{
						fireRuntime = item;
						num = sqrMagnitude;
					}
				}
			}
			return fireRuntime;
		}

		internal static void SelectVisuals()
		{
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			nearest.Clear();
			Player localPlayer = Player.m_localPlayer;
			bool flag = Plugin.Running && Plugin.Instance.Visuals.Value && (Object)(object)localPlayer != (Object)null;
			long now = Plugin.Now;
			foreach (FireRuntime item in Live)
			{
				item.selected = false;
				if (flag && item.Burning && item.Active(now, out var _, out var _))
				{
					Vector3 val = item.Center - ((Component)localPlayer).transform.position;
					item.distance = ((Vector3)(ref val)).sqrMagnitude;
					if (item.distance <= 1024f)
					{
						nearest.Add(item);
					}
				}
			}
			nearest.Sort((FireRuntime a, FireRuntime b) => a.distance.CompareTo(b.distance));
			for (int num = 0; num < Math.Min(nearest.Count, 8); num++)
			{
				nearest[num].selected = true;
			}
			foreach (FireRuntime item2 in Live)
			{
				if (!item2.selected)
				{
					item2.Restore();
				}
			}
		}

		internal static void TickVisuals()
		{
			long now = Plugin.Now;
			foreach (FireRuntime item in Live)
			{
				if (!item.selected || !Plugin.Running || !Plugin.Instance.Visuals.Value || !item.Burning || !item.Active(now, out var salt, out var start))
				{
					item.Restore();
					continue;
				}
				if (item.Visual == null)
				{
					item.Visual = new FireVisual(item);
				}
				item.Visual.Tick(salt, start, now);
			}
		}

		internal void Restore()
		{
			Visual?.Dispose();
			Visual = null;
		}

		internal static void RestoreAll()
		{
			foreach (FireRuntime item in Live)
			{
				if ((Object)(object)item != (Object)null)
				{
					item.Restore();
				}
			}
		}

		internal static void DetachAll()
		{
			RestoreAll();
			FireRuntime[] array = Live.ToArray();
			foreach (FireRuntime fireRuntime in array)
			{
				if ((Object)(object)fireRuntime != (Object)null)
				{
					Object.Destroy((Object)(object)fireRuntime);
				}
			}
			Live.Clear();
			nearest.Clear();
			cursor = 0;
			FireVisual.DisposeShared();
		}
	}
	internal sealed class FireVisual : IDisposable
	{
		private sealed class ParticleSnapshot
		{
			internal ParticleSystem System;

			internal MinMaxGradient Start;

			internal MinMaxGradient Lifetime;

			internal bool LifetimeEnabled;

			internal ParticleSystemRenderer Renderer;

			internal MaterialPropertyBlock Properties;
		}

		private sealed class LightSnapshot
		{
			internal Light Light;

			internal Color Color;
		}

		private readonly FireRuntime fire;

		private readonly List<ParticleSnapshot> particles = new List<ParticleSnapshot>();

		private readonly List<LightSnapshot> lights = new List<LightSnapshot>();

		private GameObject effects;

		private ParticleSystem sparks;

		private AudioSource sound;

		private static AudioClip pop;

		private static AudioClip crackle;

		private int lastSalt;

		private int lastPulse;

		private long lastStart;

		internal FireVisual(FireRuntime fire)
		{
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Expected O, but got Unknown
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0204: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_0195: Unknown result type (might be due to invalid IL or missing references)
			this.fire = fire;
			HashSet<GameObject> hashSet = new HashSet<GameObject>();
			if ((Object)(object)fire.Fire.m_enabledObject != (Object)null)
			{
				hashSet.Add(fire.Fire.m_enabledObject);
			}
			if ((Object)(object)fire.Fire.m_enabledObjectHigh != (Object)null)
			{
				hashSet.Add(fire.Fire.m_enabledObjectHigh);
			}
			if ((Object)(object)fire.Fire.m_enabledObjectLow != (Object)null)
			{
				hashSet.Add(fire.Fire.m_enabledObjectLow);
			}
			HashSet<ParticleSystem> hashSet2 = new HashSet<ParticleSystem>();
			HashSet<Light> hashSet3 = new HashSet<Light>();
			foreach (GameObject item in hashSet)
			{
				ParticleSystem[] componentsInChildren = item.GetComponentsInChildren<ParticleSystem>(true);
				foreach (ParticleSystem val in componentsInChildren)
				{
					string text = ((Object)val).name.ToLowerInvariant();
					if (!text.Contains("smok") && (text.Contains("flame") || text.Contains("flare") || text.Contains("spar")) && hashSet2.Add(val))
					{
						ParticleSystemRenderer component = ((Component)val).GetComponent<ParticleSystemRenderer>();
						MaterialPropertyBlock val2 = new MaterialPropertyBlock();
						if ((Object)(object)component != (Object)null)
						{
							((Renderer)component).GetPropertyBlock(val2);
						}
						List<ParticleSnapshot> list = particles;
						ParticleSnapshot obj = new ParticleSnapshot
						{
							System = val
						};
						MainModule main = val.main;
						obj.Start = ((MainModule)(ref main)).startColor;
						ColorOverLifetimeModule colorOverLifetime = val.colorOverLifetime;
						obj.Lifetime = ((ColorOverLifetimeModule)(ref colorOverLifetime)).color;
						colorOverLifetime = val.colorOverLifetime;
						obj.LifetimeEnabled = ((ColorOverLifetimeModule)(ref colorOverLifetime)).enabled;
						obj.Renderer = component;
						obj.Properties = val2;
						list.Add(obj);
					}
				}
				Light[] componentsInChildren2 = item.GetComponentsInChildren<Light>(true);
				foreach (Light val3 in componentsInChildren2)
				{
					if (hashSet3.Add(val3))
					{
						lights.Add(new LightSnapshot
						{
							Light = val3,
							Color = val3.color
						});
					}
				}
			}
			CreateAccents();
		}

		private void CreateAccents()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			//IL_0037: 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_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_00be: 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_00e0: 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_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: 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_0122: 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_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: 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_0185: Expected O, but got Unknown
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01af: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
			effects = new GameObject("FireSalts_DecorativeAccents");
			effects.transform.SetParent(((Component)fire).transform, false);
			effects.transform.localPosition = Vector3.up * ((fire.Prefab == "bonfire") ? 1.2f : 0.35f);
			effects.SetActive(false);
			sparks = effects.AddComponent<ParticleSystem>();
			MainModule main = sparks.main;
			((MainModule)(ref main)).playOnAwake = false;
			((MainModule)(ref main)).loop = true;
			((MainModule)(ref main)).duration = 30f;
			((MainModule)(ref main)).maxParticles = 24;
			((MainModule)(ref main)).startLifetime = MinMaxCurve.op_Implicit(0.7f);
			((MainModule)(ref main)).startSpeed = MinMaxCurve.op_Implicit(1.5f);
			((MainModule)(ref main)).startSize = MinMaxCurve.op_Implicit(0.035f);
			((MainModule)(ref main)).gravityModifier = MinMaxCurve.op_Implicit(0.7f);
			((MainModule)(ref main)).simulationSpace = (ParticleSystemSimulationSpace)1;
			EmissionModule emission = sparks.emission;
			((EmissionModule)(ref emission)).enabled = false;
			ShapeModule shape = sparks.shape;
			((ShapeModule)(ref shape)).enabled = false;
			CollisionModule collision = sparks.collision;
			((CollisionModule)(ref collision)).enabled = false;
			SubEmittersModule subEmitters = sparks.subEmitters;
			((SubEmittersModule)(ref subEmitters)).enabled = false;
			LightsModule val = sparks.lights;
			((LightsModule)(ref val)).enabled = false;
			ColorOverLifetimeModule colorOverLifetime = sparks.colorOverLifetime;
			((ColorOverLifetimeModule)(ref colorOverLifetime)).enabled = true;
			Gradient val2 = new Gradient();
			val2.SetKeys((GradientColorKey[])(object)new GradientColorKey[2]
			{
				new GradientColorKey(Color.white, 0f),
				new GradientColorKey(Color.white, 1f)
			}, (GradientAlphaKey[])(object)new GradientAlphaKey[2]
			{
				new GradientAlphaKey(1f, 0f),
				new GradientAlphaKey(0f, 1f)
			});
			((ColorOverLifetimeModule)(ref colorOverLifetime)).color = MinMaxGradient.op_Implicit(val2);
			ParticleSystemRenderer component = ((Component)sparks).GetComponent<ParticleSystemRenderer>();
			component.renderMode = (ParticleSystemRenderMode)0;
			Material val3 = null;
			foreach (ParticleSnapshot particle in particles)
			{
				if (((Object)particle.System).name.ToLowerInvariant().Contains("spar") && (Object)(object)particle.Renderer != (Object)null)
				{
					val3 = ((Renderer)particle.Renderer).sharedMaterial;
					break;
				}
			}
			if ((Object)(object)val3 == (Object)null && (Object)(object)ZNetScene.instance != (Object)null)
			{
				GameObject prefab = ZNetScene.instance.GetPrefab("bonfire");
				if ((Object)(object)prefab != (Object)null)
				{
					ParticleSystem[] componentsInChildren = prefab.GetComponentsInChildren<ParticleSystem>(true);
					foreach (ParticleSystem val4 in componentsInChildren)
					{
						if (((Object)val4).name == "Sparks")
						{
							ParticleSystemRenderer component2 = ((Component)val4).GetComponent<ParticleSystemRenderer>();
							val3 = ((component2 != null) ? ((Renderer)component2).sharedMaterial : null);
							break;
						}
					}
				}
			}
			((Renderer)component).sharedMaterial = val3;
			((Renderer)component).enabled = (Object)(object)val3 != (Object)null;
			if ((Object)(object)pop == (Object)null)
			{
				pop = MakeSound("FireSalts_OriginalPop", isCrackle: false);
			}
			if ((Object)(object)crackle == (Object)null)
			{
				crackle = MakeSound("FireSalts_OriginalCrackle", isCrackle: true);
			}
			sound = effects.AddComponent<AudioSource>();
			sound.playOnAwake = false;
			sound.loop = false;
			sound.spatialBlend = 1f;
			sound.volume = 0.12f;
			sound.minDistance = 1f;
			sound.maxDistance = 12f;
			sound.rolloffMode = (AudioRolloffMode)1;
			sound.dopplerLevel = 0f;
			sound.priority = 180;
			effects.SetActive(true);
			sparks.Play(false);
		}

		private static AudioClip MakeSound(string name, bool isCrackle)
		{
			float[] array = new float[isCrackle ? 3840 : 1920];
			Random random = new Random(isCrackle ? 671 : 193);
			float num = 0f;
			for (int i = 0; i < array.Length; i++)
			{
				double num2 = (double)i / 24000.0;
				float num3 = (float)(random.NextDouble() * 2.0 - 1.0);
				num = num * 0.45f + num3 * 0.55f;
				double num4 = Math.Exp((0.0 - num2) * (double)(isCrackle ? 32 : 75));
				num4 = ((!isCrackle) ? (num4 * Math.Min(1.0, (double)i / 20.0)) : (num4 * (0.3 + 0.7 * Math.Pow(Math.Sin(num2 * 190.0), 8.0))));
				array[i] = (float)((double)num * num4 * 0.6);
			}
			AudioClip obj = AudioClip.Create(name, array.Length, 1, 24000, false);
			obj.SetData(array, 0);
			return obj;
		}

		internal void Tick(int saltId, long start, long now)
		{
			//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_0078: 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_0082: 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_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Expected O, but got Unknown
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: 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_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_0274: Unknown result type (might be due to invalid IL or missing references)
			//IL_0287: Unknown result type (might be due to invalid IL or missing references)
			//IL_02be: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0335: Unknown result type (might be due to invalid IL or missing references)
			//IL_0340: Unknown result type (might be due to invalid IL or missing references)
			//IL_0345: Unknown result type (might be due to invalid IL or missing references)
			//IL_034a: Unknown result type (might be due to invalid IL or missing references)
			Color color = Salts.Get(saltId).Color;
			if (saltId != lastSalt || start != lastStart)
			{
				lastSalt = saltId;
				lastStart = start;
				lastPulse = Rules.Pulse(now, start) - ((now - start < 5000000) ? 1 : 0);
				foreach (ParticleSnapshot particle in particles)
				{
					if ((Object)(object)particle.System == (Object)null)
					{
						continue;
					}
					MainModule main = particle.System.main;
					((MainModule)(ref main)).startColor = Tint(particle.Start, color);
					ColorOverLifetimeModule colorOverLifetime = particle.System.colorOverLifetime;
					((ColorOverLifetimeModule)(ref colorOverLifetime)).color = Tint(particle.Lifetime, Color.white);
					((ColorOverLifetimeModule)(ref colorOverLifetime)).enabled = particle.LifetimeEnabled;
					if (!((Object)(object)particle.Renderer != (Object)null) || !((Object)(object)((Renderer)particle.Renderer).sharedMaterial != (Object)null))
					{
						continue;
					}
					MaterialPropertyBlock val = new MaterialPropertyBlock();
					((Renderer)particle.Renderer).GetPropertyBlock(val);
					string[] array = new string[2] { "_TintColor", "_Color" };
					foreach (string text in array)
					{
						Material sharedMaterial = ((Renderer)particle.Renderer).sharedMaterial;
						if (sharedMaterial.HasProperty(text))
						{
							Color color2 = sharedMaterial.GetColor(text);
							float num = Mathf.Max(color2.r, Mathf.Max(color2.g, color2.b));
							val.SetColor(text, new Color(num, num, num, color2.a));
						}
					}
					((Renderer)particle.Renderer).SetPropertyBlock(val);
				}
			}
			foreach (LightSnapshot light in lights)
			{
				if ((Object)(object)light.Light != (Object)null)
				{
					light.Light.color = Recolor(light.Color, color);
				}
			}
			if (!Plugin.Instance.Sound.Value && (Object)(object)sound != (Object)null)
			{
				sound.Stop();
			}
			int num2 = Rules.Pulse(now, start);
			if (num2 <= lastPulse)
			{
				return;
			}
			lastPulse = num2;
			for (int j = 0; j < 5; j++)
			{
				float num3 = (float)(num2 * 73 + j * 137) * (MathF.PI / 180f);
				EmitParams val2 = default(EmitParams);
				((EmitParams)(ref val2)).position = effects.transform.position;
				((EmitParams)(ref val2)).velocity = new Vector3(Mathf.Cos(num3) * 0.6f, 1.3f + (float)(j % 3) * 0.3f, Mathf.Sin(num3) * 0.6f);
				((EmitParams)(ref val2)).startColor = Color32.op_Implicit(color);
				((EmitParams)(ref val2)).startLifetime = 0.7f;
				((EmitParams)(ref val2)).startSize = 0.035f;
				EmitParams val3 = val2;
				sparks.Emit(val3, 1);
			}
			if (Plugin.Instance.Sound.Value && (Object)(object)Player.m_localPlayer != (Object)null)
			{
				Vector3 val4 = ((Component)Player.m_localPlayer).transform.position - fire.Center;
				if (((Vector3)(ref val4)).sqrMagnitude <= 144f)
				{
					sound.PlayOneShot((num2 % 3 == 0) ? pop : crackle);
				}
			}
		}

		private static MinMaxGradient Tint(MinMaxGradient original, Color color)
		{
			//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)
			//IL_0008: 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_0020: Expected I4, but got Unknown
			//IL_002b: 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_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: 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_006e: 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_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: 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_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			ParticleSystemGradientMode mode = ((MinMaxGradient)(ref original)).mode;
			switch (mode - 1)
			{
			case 0:
			case 3:
			{
				MinMaxGradient result = default(MinMaxGradient);
				((MinMaxGradient)(ref result))..ctor(TintGradient(((MinMaxGradient)(ref original)).gradient, color));
				((MinMaxGradient)(ref result)).mode = ((MinMaxGradient)(ref original)).mode;
				return result;
			}
			case 2:
				return new MinMaxGradient(TintGradient(((MinMaxGradient)(ref original)).gradientMin, color), TintGradient(((MinMaxGradient)(ref original)).gradientMax, color));
			case 1:
				return new MinMaxGradient(Recolor(((MinMaxGradient)(ref original)).colorMin, color), Recolor(((MinMaxGradient)(ref original)).colorMax, color));
			default:
				return new MinMaxGradient(Recolor(((MinMaxGradient)(ref original)).color, color));
			}
		}

		private static Color Recolor(Color original, Color tint)
		{
			//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_0025: 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_0035: 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)
			float num = Mathf.Max(original.r, Mathf.Max(original.g, original.b));
			return new Color(tint.r * num, tint.g * num, tint.b * num, original.a);
		}

		private static Gradient TintGradient(Gradient original, Color color)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			//IL_0011: 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_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_0051: 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_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: 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_0093: 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_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			Gradient val = new Gradient();
			GradientColorKey[] array = (GradientColorKey[])((original != null) ? ((Array)original.colorKeys) : ((Array)new GradientColorKey[2]
			{
				new GradientColorKey(Color.white, 0f),
				new GradientColorKey(Color.white, 1f)
			}));
			for (int i = 0; i < array.Length; i++)
			{
				array[i] = new GradientColorKey(Recolor(array[i].color, color), array[i].time);
			}
			val.SetKeys(array, (GradientAlphaKey[])((original != null) ? ((Array)original.alphaKeys) : ((Array)new GradientAlphaKey[2]
			{
				new GradientAlphaKey(1f, 0f),
				new GradientAlphaKey(1f, 1f)
			})));
			if (original != null)
			{
				val.mode = original.mode;
			}
			return val;
		}

		public void Dispose()
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0048: 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_00cb: Unknown result type (might be due to invalid IL or missing references)
			foreach (ParticleSnapshot particle in particles)
			{
				if (!((Object)(object)particle.System == (Object)null))
				{
					MainModule main = particle.System.main;
					((MainModule)(ref main)).startColor = particle.Start;
					ColorOverLifetimeModule colorOverLifetime = particle.System.colorOverLifetime;
					((ColorOverLifetimeModule)(ref colorOverLifetime)).color = particle.Lifetime;
					((ColorOverLifetimeModule)(ref colorOverLifetime)).enabled = particle.LifetimeEnabled;
					if ((Object)(object)particle.Renderer != (Object)null)
					{
						((Renderer)particle.Renderer).SetPropertyBlock(particle.Properties);
					}
				}
			}
			foreach (LightSnapshot light in lights)
			{
				if ((Object)(object)light.Light != (Object)null)
				{
					light.Light.color = light.Color;
				}
			}
			if ((Object)(object)sparks != (Object)null)
			{
				sparks.Stop(true, (ParticleSystemStopBehavior)0);
			}
			if ((Object)(object)sound != (Object)null)
			{
				sound.Stop();
			}
			if ((Object)(object)effects != (Object)null)
			{
				effects.SetActive(false);
				Object.Destroy((Object)(object)effects);
			}
			particles.Clear();
			lights.Clear();
		}

		internal static void DisposeShared()
		{
			if ((Object)(object)pop != (Object)null)
			{
				Object.Destroy((Object)(object)pop);
			}
			if ((Object)(object)crackle != (Object)null)
			{
				Object.Destroy((Object)(object)crackle);
			}
			pop = null;
			crackle = null;
		}
	}
	internal static class ItemIcons
	{
		internal const int Size = 256;

		internal static bool TryLoad(Salt salt, out Texture2D texture, out Sprite sprite)
		{
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Expected O, but got Unknown
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			texture = null;
			sprite = null;
			string name = "FireSalts.ItemIcons." + salt.Prefab + ".png";
			using Stream stream = typeof(ItemIcons).Assembly.GetManifestResourceStream(name);
			if (stream == null)
			{
				return false;
			}
			try
			{
				if (stream.Length < 24 || stream.Length > 524288)
				{
					throw new InvalidDataException("Unexpected PNG size");
				}
				byte[] array;
				using (MemoryStream memoryStream = new MemoryStream())
				{
					stream.CopyTo(memoryStream);
					array = memoryStream.ToArray();
				}
				byte[] array2 = new byte[8] { 137, 80, 78, 71, 13, 10, 26, 10 };
				for (int i = 0; i < array2.Length; i++)
				{
					if (array[i] != array2[i])
					{
						throw new InvalidDataException("Not a PNG");
					}
				}
				if (ReadInt(array, 16) != 256 || ReadInt(array, 20) != 256)
				{
					throw new InvalidDataException("Item PNG must be 256x256");
				}
				texture = new Texture2D(2, 2, (TextureFormat)4, false, false)
				{
					name = salt.Prefab + "_InventoryIcon",
					filterMode = (FilterMode)1,
					wrapMode = (TextureWrapMode)1
				};
				if (!ImageConversion.LoadImage(texture, array, true))
				{
					throw new InvalidDataException("PNG decode failed");
				}
				sprite = Sprite.Create(texture, new Rect(0f, 0f, 256f, 256f), new Vector2(0.5f, 0.5f), 256f, 0u, (SpriteMeshType)0);
				((Object)sprite).name = salt.Prefab + "_InventorySprite";
				return true;
			}
			catch (Exception ex)
			{
				if ((Object)(object)sprite != (Object)null)
				{
					Object.Destroy((Object)(object)sprite);
				}
				if ((Object)(object)texture != (Object)null)
				{
					Object.Destroy((Object)(object)texture);
				}
				sprite = null;
				texture = null;
				Plugin.Warn("Could not load item artwork for " + salt.Prefab + "; using placeholder: " + ex.Message);
				return false;
			}
		}

		private static int ReadInt(byte[] data, int at)
		{
			return (data[at] << 24) | (data[at + 1] << 16) | (data[at + 2] << 8) | data[at + 3];
		}
	}
	[BepInPlugin("smeagsmods.firesalts", "Fire Salts", "0.1.1")]
	public sealed class Plugin : BaseUnityPlugin
	{
		[HarmonyPatch(typeof(ObjectDB), "Awake")]
		private static class DatabaseAwake
		{
			[HarmonyPostfix]
			private static void Postfix(ObjectDB __instance)
			{
				Registration.RegisterItems(__instance);
			}
		}

		[HarmonyPatch(typeof(ObjectDB), "CopyOtherDB")]
		private static class DatabaseCopy
		{
			[HarmonyPostfix]
			private static void Postfix(ObjectDB __instance)
			{
				Registration.RegisterItems(__instance);
			}
		}

		[HarmonyPatch(typeof(ZNetScene), "Awake")]
		private static class SceneAwake
		{
			[HarmonyPostfix]
			private static void Postfix(ZNetScene __instance)
			{
				Registration.RegisterNetwork(__instance);
			}
		}

		[HarmonyPatch(typeof(Fireplace), "Awake")]
		private static class FireAwake
		{
			[HarmonyPostfix]
			private static void Postfix(Fireplace __instance)
			{
				if (Running)
				{
					FireRuntime.Attach(__instance);
				}
			}
		}

		[HarmonyPatch(typeof(ItemDrop), "Awake")]
		private static class SaltAwake
		{
			[HarmonyPostfix]
			private static void Postfix(ItemDrop __instance)
			{
				if (Salts.Get(__instance) != null)
				{
					__instance.m_autoPickup = false;
				}
			}
		}

		[HarmonyPatch(typeof(ItemDrop), "AutoStackItems")]
		private static class SaltGroundStack
		{
			[HarmonyPrefix]
			private static bool Prefix(ItemDrop __instance)
			{
				return Salts.Get(__instance) == null;
			}
		}

		[HarmonyPatch(typeof(ItemDrop), "OnPlayerDrop")]
		private static class ArmToss
		{
			[HarmonyPostfix]
			private static void Postfix(ItemDrop __instance)
			{
				if (Running && Salts.Get(__instance) != null)
				{
					ZNetView component = ((Component)__instance).GetComponent<ZNetView>();
					if ((Object)(object)component != (Object)null && component.IsValid() && component.IsOwner())
					{
						component.GetZDO().Set("smeagsmods.firesalts.armed.v1", Rules.Expiry(Now, 12));
					}
				}
			}
		}

		[HarmonyPatch(typeof(Humanoid), "UseItem")]
		private static class TossFromHotbar
		{
			[HarmonyPrefix]
			private static bool Prefix(Humanoid __instance, Inventory inventory, ItemData item, bool fromInventoryGui)
			{
				if (!Running || Salts.Get(item) == null)
				{
					return true;
				}
				if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer)
				{
					return false;
				}
				if (fromInventoryGui)
				{
					((Character)__instance).Message((MessageType)2, "Put this salt on your hotbar to toss one, or drop it onto a burning fire.", 0, (Sprite)null, false);
					return false;
				}
				Inventory inventory2 = __instance.GetInventory();
				if ((inventory != null && inventory != inventory2) || !inventory2.ContainsItem(item) || Time.unscaledTime < nextToss)
				{
					return false;
				}
				if (((Character)__instance).IsDead() || ((Character)__instance).InAttack() || ((Character)__instance).IsTeleporting())
				{
					return false;
				}
				nextToss = Time.unscaledTime + 0.6f;
				__instance.DropItem(inventory2, item, 1);
				return false;
			}
		}

		public const string Id = "smeagsmods.firesalts";

		internal static Plugin Instance;

		internal ConfigEntry<bool> Visuals;

		internal ConfigEntry<bool> Sound;

		private Harmony harmony;

		private float nextScan;

		private static float nextToss;

		internal static bool Running
		{
			get
			{
				if ((Object)(object)Instance != (Object)null)
				{
					return ((Behaviour)Instance).isActiveAndEnabled;
				}
				return false;
			}
		}

		internal static bool HasGraphics => (int)SystemInfo.graphicsDeviceType != 4;

		internal static long Now
		{
			get
			{
				if (!((Object)(object)ZNet.instance == (Object)null))
				{
					return ZNet.instance.GetTime().Ticks;
				}
				return 0L;
			}
		}

		private void Awake()
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Expected O, but got Unknown
			Instance = this;
			Visuals = ((BaseUnityPlugin)this).Config.Bind<bool>("Client", "Visuals", true, "Show temporary salt colors and bounded sparks. Does not change server consumption or duration.");
			Sound = ((BaseUnityPlugin)this).Config.Bind<bool>("Client", "Sound", true, "Play quiet decorative crackles and pops within 12 metres.");
			harmony = new Harmony("smeagsmods.firesalts");
			harmony.PatchAll(typeof(Plugin).Assembly);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Fire Salts 0.1.1 loaded; approved inventory art. All peers require the same version.");
		}

		private void Update()
		{
			if (!(Time.unscaledTime < nextScan))
			{
				nextScan = Time.unscaledTime + 0.1f;
				FireRuntime.TickAuthority();
				if (HasGraphics)
				{
					FireRuntime.SelectVisuals();
				}
			}
		}

		private void LateUpdate()
		{
			if (HasGraphics)
			{
				FireRuntime.TickVisuals();
			}
		}

		private void OnDisable()
		{
			FireRuntime.RestoreAll();
		}

		private void OnDestroy()
		{
			FireRuntime.DetachAll();
			Harmony obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
			Registration.Dispose();
			if ((Object)(object)Instance == (Object)(object)this)
			{
				Instance = null;
			}
		}

		internal static void Log(string message)
		{
			Plugin instance = Instance;
			if (instance != null)
			{
				((BaseUnityPlugin)instance).Logger.LogInfo((object)message);
			}
		}

		internal static void Warn(string message)
		{
			Plugin instance = Instance;
			if (instance != null)
			{
				((BaseUnityPlugin)instance).Logger.LogWarning((object)message);
			}
		}
	}
	internal static class Reaction
	{
		internal static bool Apply(int salt, long now, long armedUntil, Action<long> setArmed, Func<bool> removeOne, Action<string> publish)
		{
			if (!Rules.IsSalt(salt) || !Rules.IsArmed(armedUntil, now))
			{
				return false;
			}
			setArmed(0L);
			if (!removeOne())
			{
				setArmed(armedUntil);
				return false;
			}
			publish(Rules.Pack(salt, now));
			return true;
		}
	}
	internal static class Registration
	{
		private static GameObject root;

		private static readonly Dictionary<string, GameObject> prefabs = new Dictionary<string, GameObject>();

		private static readonly List<Object> owned = new List<Object>();

		private static readonly List<Recipe> recipes = new List<Recipe>();

		private static readonly List<ObjectDB> databases = new List<ObjectDB>();

		private static readonly MethodInfo updateRegisters = AccessTools.Method(typeof(ObjectDB), "UpdateRegisters", (Type[])null, (Type[])null);

		private static readonly FieldInfo namedPrefabs = AccessTools.Field(typeof(ZNetScene), "m_namedPrefabs");

		internal static void RegisterItems(ObjectDB db)
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Expected O, but got Unknown
			//IL_00ed: 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_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Expected O, but got Unknown
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Expected O, but got Unknown
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_020d: Expected O, but got Unknown
			//IL_0223: Unknown result type (might be due to invalid IL or missing references)
			if (!Plugin.Running || (Object)(object)db == (Object)null || (Object)(object)db.GetItemPrefab("Resin") == (Object)null)
			{
				return;
			}
			if (!databases.Contains(db))
			{
				databases.Add(db);
			}
			if ((Object)(object)root == (Object)null)
			{
				root = new GameObject("FireSalts_Prefabs");
				root.SetActive(false);
				Object.DontDestroyOnLoad((Object)(object)root);
			}
			Salt[] all = Salts.All;
			foreach (Salt salt in all)
			{
				if (!prefabs.TryGetValue(salt.Prefab, out var value))
				{
					if ((Object)(object)db.GetItemPrefab(salt.Prefab) != (Object)null)
					{
						throw new InvalidOperationException("Fire Salts prefab name is already registered: " + salt.Prefab);
					}
					value = Object.Instantiate<GameObject>(db.GetItemPrefab("Resin"), root.transform, false);
					((Object)value).name = salt.Prefab;
					value.transform.localPosition = Vector3.zero;
					value.transform.localRotation = Quaternion.identity;
					ItemDrop component = value.GetComponent<ItemDrop>();
					ItemData val = new ItemData();
					val.m_dropPrefab = value;
					SharedData val2 = new SharedData();
					val2.m_name = salt.Name;
					val2.m_description = "A pinch of " + salt.Name.ToLowerInvariant() + ". Toss onto a burning campfire, hearth or bonfire for 30 seconds of colored flame.\nHotbar: toss one. Misses can be picked up by hand.\n<color=#b6a8c8>Dropped world item uses a tinted native resin model.</color>";
					val2.m_itemType = (ItemType)1;
					val2.m_icons = (Sprite[])(object)new Sprite[1] { MakeIcon(salt) };
					val2.m_maxStackSize = 20;
					val2.m_weight = 0.1f;
					val2.m_maxQuality = 1;
					val2.m_autoStack = false;
					val2.m_teleportable = true;
					val.m_shared = val2;
					component.m_itemData = val;
					component.m_autoPickup = false;
					MeshRenderer[] componentsInChildren = value.GetComponentsInChildren<MeshRenderer>(true);
					foreach (MeshRenderer val3 in componentsInChildren)
					{
						Material[] sharedMaterials = ((Renderer)val3).sharedMaterials;
						for (int k = 0; k < sharedMaterials.Length; k++)
						{
							if (!((Object)(object)sharedMaterials[k] == (Object)null))
							{
								Material val4 = new Material(sharedMaterials[k])
								{
									name = salt.Prefab + "_Placeholder"
								};
								if (val4.HasProperty("_Color"))
								{
									val4.SetColor("_Color", salt.Color);
								}
								sharedMaterials[k] = val4;
								owned.Add((Object)(object)val4);
							}
						}
						((Renderer)val3).sharedMaterials = sharedMaterials;
					}
					prefabs.Add(salt.Prefab, value);
				}
				if (!db.m_items.Contains(value))
				{
					db.m_items.Add(value);
				}
			}
			updateRegisters.Invoke(db, null);
			AddRecipes(db);
			if ((Object)(object)ZNetScene.instance != (Object)null)
			{
				AddNetworkPrefabs(ZNetScene.instance);
			}
		}

		private static Sprite MakeIcon(Salt salt)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Expected O, but got Unknown
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: 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_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: 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_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_011e: 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_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			if (ItemIcons.TryLoad(salt, out var texture, out var sprite))
			{
				owned.Add((Object)(object)texture);
				owned.Add((Object)(object)sprite);
				return sprite;
			}
			Texture2D val = new Texture2D(64, 64, (TextureFormat)4, false)
			{
				name = salt.Prefab + "_PlaceholderIcon",
				filterMode = (FilterMode)0
			};
			Color[] array = (Color[])(object)new Color[4096];
			for (int i = 0; i < 64; i++)
			{
				for (int j = 0; j < 64; j++)
				{
					float num = Math.Abs((float)j - 32f) / 21f + Math.Abs((float)i - 35f) / 25f;
					if (num < 1f)
					{
						array[i * 64 + j] = Color.Lerp(salt.Color * 0.55f, Color.white, (j < 32) ? 0.3f : 0.04f);
					}
					if (num < 0.85f && j < 31)
					{
						array[i * 64 + j] = salt.Color;
					}
					for (int k = 0; k < salt.Id; k++)
					{
						if (Math.Abs(j - (26 + k * 7)) <= 2 && i >= 4 && i <= 8)
						{
							array[i * 64 + j] = Color.white;
						}
					}
					if (j >= 52 && i >= 52)
					{
						array[i * 64 + j] = (((j / 3 + i / 3) % 2 == 0) ? Color.magenta : Color.black);
					}
				}
			}
			val.SetPixels(array);
			val.Apply();
			Sprite val2 = Sprite.Create(val, new Rect(0f, 0f, 64f, 64f), new Vector2(0.5f, 0.5f), 64f);
			owned.Add((Object)(object)val);
			owned.Add((Object)(object)val2);
			return val2;
		}

		private static void AddRecipes(ObjectDB db)
		{
			CraftingStation val = (from r in db.m_recipes
				where (Object)(object)r != (Object)null && (Object)(object)r.m_craftingStation != (Object)null
				select r.m_craftingStation).FirstOrDefault((Func<CraftingStation, bool>)((CraftingStation s) => ((Object)s).name == "piece_workbench"));
			if ((Object)(object)val == (Object)null && (Object)(object)ZNetScene.instance != (Object)null)
			{
				GameObject prefab = ZNetScene.instance.GetPrefab("piece_workbench");
				val = ((prefab != null) ? prefab.GetComponent<CraftingStation>() : null);
			}
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			Salt[] all = Salts.All;
			foreach (Salt salt in all)
			{
				string name = "Recipe_" + salt.Prefab;
				if (db.m_recipes.Any((Recipe r) => (Object)(object)r != (Object)null && ((Object)r).name == name))
				{
					continue;
				}
				GameObject itemPrefab = db.GetItemPrefab(salt.Ingredient);
				GameObject itemPrefab2 = db.GetItemPrefab("Resin");
				GameObject itemPrefab3 = db.GetItemPrefab("Coal");
				if ((Object)(object)itemPrefab == (Object)null || (Object)(object)itemPrefab2 == (Object)null || (Object)(object)itemPrefab3 == (Object)null)
				{
					Plugin.Warn("Recipe deferred: missing native ingredient for " + name);
					continue;
				}
				Recipe val2 = ((IEnumerable<Recipe>)recipes).FirstOrDefault((Func<Recipe, bool>)((Recipe r) => ((Object)r).name == name));
				if ((Object)(object)val2 == (Object)null)
				{
					val2 = ScriptableObject.CreateInstance<Recipe>();
					((Object)val2).name = name;
					val2.m_item = prefabs[salt.Prefab].GetComponent<ItemDrop>();
					val2.m_amount = 3;
					val2.m_craftingStation = val;
					val2.m_minStationLevel = 1;
					val2.m_enabled = true;
					val2.m_resources = (Requirement[])(object)new Requirement[3]
					{
						Requirement(itemPrefab2, 2),
						Requirement(itemPrefab3, 1),
						Requirement(itemPrefab, 1)
					};
					recipes.Add(val2);
				}
				db.m_recipes.Add(val2);
			}
		}

		private static Requirement Requirement(GameObject item, int amount)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: 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_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			return new Requirement
			{
				m_resItem = item.GetComponent<ItemDrop>(),
				m_amount = amount,
				m_amountPerLevel = 0,
				m_recover = false
			};
		}

		internal static void RegisterNetwork(ZNetScene scene)
		{
			RegisterItems(ObjectDB.instance);
			AddNetworkPrefabs(scene);
			if ((Object)(object)ObjectDB.instance != (Object)null)
			{
				AddRecipes(ObjectDB.instance);
			}
		}

		private static void AddNetworkPrefabs(ZNetScene scene)
		{
			Dictionary<int, GameObject> dictionary = (Dictionary<int, GameObject>)namedPrefabs.GetValue(scene);
			foreach (KeyValuePair<string, GameObject> prefab in prefabs)
			{
				int stableHashCode = StringExtensionMethods.GetStableHashCode(prefab.Key);
				if (dictionary.TryGetValue(stableHashCode, out var value) && (Object)(object)value != (Object)(object)prefab.Value)
				{
					throw new InvalidOperationException("Fire Salts network prefab hash collision: " + prefab.Key);
				}
				dictionary[stableHashCode] = prefab.Value;
				if (!scene.m_prefabs.Contains(prefab.Value))
				{
					scene.m_prefabs.Add(prefab.Value);
				}
			}
		}

		internal static void Dispose()
		{
			foreach (ObjectDB database in databases)
			{
				if (!((Object)(object)database == (Object)null))
				{
					database.m_items.RemoveAll((GameObject p) => prefabs.Values.Contains(p));
					database.m_recipes.RemoveAll((Recipe r) => recipes.Contains(r));
					updateRegisters.Invoke(database, null);
				}
			}
			if ((Object)(object)ZNetScene.instance != (Object)null)
			{
				ZNetScene instance = ZNetScene.instance;
				Dictionary<int, GameObject> dictionary = (Dictionary<int, GameObject>)namedPrefabs.GetValue(instance);
				foreach (KeyValuePair<string, GameObject> prefab in prefabs)
				{
					int stableHashCode = StringExtensionMethods.GetStableHashCode(prefab.Key);
					if (dictionary.TryGetValue(stableHashCode, out var value) && (Object)(object)value == (Object)(object)prefab.Value)
					{
						dictionary.Remove(stableHashCode);
					}
					instance.m_prefabs.Remove(prefab.Value);
				}
			}
			foreach (Recipe recipe in recipes)
			{
				Object.Destroy((Object)(object)recipe);
			}
			if ((Object)(object)root != (Object)null)
			{
				Object.Destroy((Object)(object)root);
			}
			foreach (Object item in owned)
			{
				if (item != (Object)null)
				{
					Object.Destroy(item);
				}
			}
			recipes.Clear();
			prefabs.Clear();
			owned.Clear();
			databases.Clear();
			root = null;
		}
	}
	internal static class Rules
	{
		internal const int SaltCount = 3;

		internal const int DurationSeconds = 30;

		internal const int ArmedSeconds = 12;

		internal const int MaxVisualFires = 8;

		internal const int MaxScansPerTick = 16;

		internal const int MaxExtraParticles = 24;

		internal const float VisualRange = 32f;

		internal const string StateKey = "smeagsmods.firesalts.state.v1";

		internal const string ArmedKey = "smeagsmods.firesalts.armed.v1";

		internal static bool IsSalt(int id)
		{
			if (id >= 1)
			{
				return id <= 3;
			}
			return false;
		}

		internal static long Expiry(long start, int seconds)
		{
			if (start <= 0 || start > DateTime.MaxValue.Ticks - (long)seconds * 10000000L)
			{
				return 0L;
			}
			return start + (long)seconds * 10000000L;
		}

		internal static bool IsArmed(long until, long now)
		{
			if (now > 0 && until > now)
			{
				return until - now <= 120000000;
			}
			return false;
		}

		internal static string Pack(int salt, long start)
		{
			if (!IsSalt(salt) || Expiry(start, 30) == 0L)
			{
				return "";
			}
			return salt.ToString(CultureInfo.InvariantCulture) + ":" + start.ToString(CultureInfo.InvariantCulture);
		}

		internal static bool TryState(string raw, long now, out int salt, out long start)
		{
			salt = 0;
			start = 0L;
			if (now <= 0 || string.IsNullOrEmpty(raw) || raw.Length > 24)
			{
				return false;
			}
			string[] array = raw.Split(':');
			if (array.Length != 2 || !int.TryParse(array[0], NumberStyles.None, CultureInfo.InvariantCulture, out salt) || !long.TryParse(array[1], NumberStyles.None, CultureInfo.InvariantCulture, out start) || !IsSalt(salt))
			{
				return false;
			}
			long num = Expiry(start, 30);
			if (start <= now)
			{
				return num > now;
			}
			return false;
		}

		internal static bool CanConsume(bool fireOwner, bool itemOwner, bool burning, bool active, bool inVolume, int stack, int salt, long armedUntil, long now)
		{
			if (fireOwner && itemOwner && burning && !active && inVolume && stack > 0 && IsSalt(salt))
			{
				return IsArmed(armedUntil, now);
			}
			return false;
		}

		internal static bool InVolume(string prefab, float x, float y, float z)
		{
			if (float.IsNaN(x) || float.IsNaN(y) || float.IsNaN(z))
			{
				return false;
			}
			switch (prefab)
			{
			case "fire_pit":
				if (x * x + z * z <= 0.5184f && y >= 0.04f)
				{
					return y <= 1.15f;
				}
				return false;
			case "hearth":
				if (Math.Abs(x) <= 0.8f && Math.Abs(z) <= 1.35f && y >= 0.04f)
				{
					return y <= 1.3f;
				}
				return false;
			case "bonfire":
				if (x * x + z * z <= 1.3225f && y >= 0.2f)
				{
					return y <= 2.8f;
				}
				return false;
			default:
				return false;
			}
		}

		internal static int Pulse(long now, long start)
		{
			return (int)Math.Max(0L, (now - start) / 20000000);
		}
	}
	internal sealed class Salt
	{
		internal readonly int Id;

		internal readonly string Prefab;

		internal readonly string Name;

		internal readonly string Ingredient;

		internal readonly Color Color;

		internal Salt(int id, string prefab, string name, string ingredient, Color color)
		{
			//IL_0024: 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)
			Id = id;
			Prefab = prefab;
			Name = name;
			Ingredient = ingredient;
			Color = color;
		}
	}
	internal static class Salts
	{
		internal static readonly Salt[] All = new Salt[3]
		{
			new Salt(1, "FireSalts_Seaglass", "Seaglass Salts", "GreydwarfEye", new Color(0.12f, 1f, 0.68f)),
			new Salt(2, "FireSalts_Roseember", "Roseember Salts", "Raspberry", new Color(1f, 0.2f, 0.42f)),
			new Salt(3, "FireSalts_Moonviolet", "Moonviolet Salts", "Blueberries", new Color(0.6f, 0.26f, 1f))
		};

		internal static Salt Get(int id)
		{
			if (!Rules.IsSalt(id))
			{
				return null;
			}
			return All[id - 1];
		}

		internal static Salt Get(ItemData item)
		{
			if ((Object)(object)item?.m_dropPrefab == (Object)null)
			{
				return null;
			}
			string name = ((Object)item.m_dropPrefab).name;
			Salt[] all = All;
			foreach (Salt salt in all)
			{
				if (name == salt.Prefab)
				{
					return salt;
				}
			}
			return null;
		}

		internal static Salt Get(ItemDrop item)
		{
			if ((Object)(object)item == (Object)null)
			{
				return null;
			}
			string text = ((Object)((Component)item).gameObject).name.Replace("(Clone)", "");
			Salt[] all = All;
			foreach (Salt salt in all)
			{
				if (text == salt.Prefab)
				{
					return salt;
				}
			}
			return null;
		}
	}
}