Decompiled source of Ravenwood Crystals v2.0.4

plugins/RavenwoodCrystals/RavenwoodCrystals.dll

Decompiled a week ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("RavenwoodCrystals")]
[assembly: AssemblyDescription("Ravenwood Crystals Mod")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Ravenwood")]
[assembly: AssemblyProduct("RavenwoodCrystals")]
[assembly: AssemblyCopyright("")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("8ad799d2-7e36-4098-b363-92c0f7924b6a")]
[assembly: AssemblyFileVersion("1.0.1")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.1.0")]
namespace Ravenwood.Crystals;

public class CrystalBreakVisual : MonoBehaviour
{
	[CompilerGenerated]
	private sealed class <ForceBreakRoutine>d__9 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		public float totalDuration;

		public CrystalBreakVisual <>4__this;

		private float <stepDelay>5__1;

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

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

		[DebuggerHidden]
		public <ForceBreakRoutine>d__9(int <>1__state)
		{
			this.<>1__state = <>1__state;
		}

		[DebuggerHidden]
		void IDisposable.Dispose()
		{
			<>1__state = -2;
		}

		private bool MoveNext()
		{
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Expected O, but got Unknown
			switch (<>1__state)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				if (<>4__this.parts.Count == 0)
				{
					return false;
				}
				<stepDelay>5__1 = ((totalDuration <= 0f) ? 0f : (totalDuration / (float)Mathf.Max(1, <>4__this.parts.Count)));
				break;
			case 1:
				<>1__state = -1;
				break;
			case 2:
				<>1__state = -1;
				break;
			}
			if (<>4__this.currentIndex < <>4__this.parts.Count)
			{
				<>4__this.RemoveOneChunk();
				if (<stepDelay>5__1 <= 0f)
				{
					<>2__current = null;
					<>1__state = 1;
					return true;
				}
				<>2__current = (object)new WaitForSeconds(<stepDelay>5__1);
				<>1__state = 2;
				return true;
			}
			return false;
		}

		bool IEnumerator.MoveNext()
		{
			//ILSpy generated this explicit interface implementation from .override directive in MoveNext
			return this.MoveNext();
		}

		[DebuggerHidden]
		void IEnumerator.Reset()
		{
			throw new NotSupportedException();
		}
	}

	private readonly List<GameObject> parts = new List<GameObject>();

	private int currentIndex = 0;

	private float lastHealth;

	private bool forceBreaking;

	private WearNTear wear;

	private void Awake()
	{
		Transform[] componentsInChildren = ((Component)this).GetComponentsInChildren<Transform>(true);
		foreach (Transform val in componentsInChildren)
		{
			if ((Object)(object)val != (Object)(object)((Component)this).transform)
			{
				parts.Add(((Component)val).gameObject);
			}
		}
		for (int j = 0; j < parts.Count; j++)
		{
			int index = Random.Range(j, parts.Count);
			GameObject value = parts[j];
			parts[j] = parts[index];
			parts[index] = value;
		}
		wear = ((Component)this).GetComponent<WearNTear>();
		if ((Object)(object)wear != (Object)null)
		{
			lastHealth = wear.m_health;
		}
	}

	private void Update()
	{
		if (!forceBreaking)
		{
			if ((Object)(object)wear == (Object)null)
			{
				wear = ((Component)this).GetComponent<WearNTear>();
			}
			else if (wear.m_health < lastHealth)
			{
				RemoveOneChunk();
				lastHealth = wear.m_health;
			}
		}
	}

	public void ForceBreak(float totalDuration = 0.28f)
	{
		if (!forceBreaking)
		{
			forceBreaking = true;
			((MonoBehaviour)this).StartCoroutine(ForceBreakRoutine(totalDuration));
		}
	}

	public void ForceBreakImmediate()
	{
		if (!forceBreaking)
		{
			forceBreaking = true;
			while (currentIndex < parts.Count)
			{
				RemoveOneChunk();
			}
		}
	}

	[IteratorStateMachine(typeof(<ForceBreakRoutine>d__9))]
	private IEnumerator ForceBreakRoutine(float totalDuration)
	{
		//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
		return new <ForceBreakRoutine>d__9(0)
		{
			<>4__this = this,
			totalDuration = totalDuration
		};
	}

	private void RemoveOneChunk()
	{
		if (currentIndex < parts.Count)
		{
			if ((Object)(object)parts[currentIndex] != (Object)null)
			{
				parts[currentIndex].SetActive(false);
			}
			currentIndex++;
		}
	}
}
public static class CrystalConfigFile
{
	public sealed class CrystalDefinition
	{
		public string PrefabName;

		public string DefaultDropItem;

		public int DefaultDropMin;

		public int DefaultDropMax;

		public bool IsRavenCrystal;

		public ConfigEntry<string> DropItem;

		public ConfigEntry<int> DropMin;

		public ConfigEntry<int> DropMax;

		public ConfigEntry<string>[] RavenDropItems = new ConfigEntry<string>[4];

		public ConfigEntry<int>[] RavenDropMins = new ConfigEntry<int>[4];

		public ConfigEntry<int>[] RavenDropMaxs = new ConfigEntry<int>[4];
	}

	private const int RavenDropSlotCount = 4;

	private static readonly List<CrystalDefinition> CrystalDefinitions = new List<CrystalDefinition>();

	public static IReadOnlyList<CrystalDefinition> Definitions => CrystalDefinitions;

	public static void Initialize(ConfigFile configFile)
	{
		if (configFile != null)
		{
			BuildCrystalDefinitions();
			BindCrystalConfigs(configFile);
		}
	}

	public static void BuildCrystalDefinitions()
	{
		if (CrystalDefinitions.Count <= 0)
		{
			CrystalDefinitions.Add(CreateCrystalDefinition("Poison_Crystal_Small", "Essence_Poison", 2, 2, isRavenCrystal: false));
			CrystalDefinitions.Add(CreateCrystalDefinition("Poison_Crystal", "Essence_Poison", 5, 5, isRavenCrystal: false));
			CrystalDefinitions.Add(CreateCrystalDefinition("Poison_Crystal_Large", "Essence_Poison", 10, 10, isRavenCrystal: false));
			CrystalDefinitions.Add(CreateCrystalDefinition("Frost_Crystal_Small", "Essence_Frost", 2, 2, isRavenCrystal: false));
			CrystalDefinitions.Add(CreateCrystalDefinition("Frost_Crystal", "Essence_Frost", 5, 5, isRavenCrystal: false));
			CrystalDefinitions.Add(CreateCrystalDefinition("Frost_Crystal_Large", "Essence_Frost", 10, 10, isRavenCrystal: false));
			CrystalDefinitions.Add(CreateCrystalDefinition("Fire_Crystal_Small", "Essence_Fire", 2, 2, isRavenCrystal: false));
			CrystalDefinitions.Add(CreateCrystalDefinition("Fire_Crystal", "Essence_Fire", 5, 5, isRavenCrystal: false));
			CrystalDefinitions.Add(CreateCrystalDefinition("Fire_Crystal_Large", "Essence_Fire", 10, 10, isRavenCrystal: false));
			CrystalDefinitions.Add(CreateCrystalDefinition("Lightning_Crystal_Small", "Essence_Lightning", 2, 2, isRavenCrystal: false));
			CrystalDefinitions.Add(CreateCrystalDefinition("Lightning_Crystal", "Essence_Lightning", 5, 5, isRavenCrystal: false));
			CrystalDefinitions.Add(CreateCrystalDefinition("Lightning_Crystal_Large", "Essence_Lightning", 10, 10, isRavenCrystal: false));
			CrystalDefinitions.Add(CreateCrystalDefinition("Raven_Crystal_Small", string.Empty, 2, 2, isRavenCrystal: true));
			CrystalDefinitions.Add(CreateCrystalDefinition("Raven_Crystal", string.Empty, 3, 3, isRavenCrystal: true));
			CrystalDefinitions.Add(CreateCrystalDefinition("Raven_Crystal_Large", string.Empty, 5, 5, isRavenCrystal: true));
		}
	}

	private static CrystalDefinition CreateCrystalDefinition(string prefabName, string defaultDropItem, int defaultDropMin, int defaultDropMax, bool isRavenCrystal)
	{
		CrystalDefinition crystalDefinition = new CrystalDefinition();
		crystalDefinition.PrefabName = prefabName;
		crystalDefinition.DefaultDropItem = defaultDropItem;
		crystalDefinition.DefaultDropMin = defaultDropMin;
		crystalDefinition.DefaultDropMax = defaultDropMax;
		crystalDefinition.IsRavenCrystal = isRavenCrystal;
		return crystalDefinition;
	}

	private static void BindCrystalConfigs(ConfigFile config)
	{
		for (int i = 0; i < CrystalDefinitions.Count; i++)
		{
			CrystalDefinition crystalDefinition = CrystalDefinitions[i];
			string text = "Crystal." + crystalDefinition.PrefabName;
			if (!crystalDefinition.IsRavenCrystal)
			{
				crystalDefinition.DropItem = config.Bind<string>(text, "DropItem", crystalDefinition.DefaultDropItem, "Drop item prefab for " + crystalDefinition.PrefabName + ".");
				crystalDefinition.DropMin = config.Bind<int>(text, "DropMin", crystalDefinition.DefaultDropMin, "Minimum drop amount for " + crystalDefinition.PrefabName + ".");
				crystalDefinition.DropMax = config.Bind<int>(text, "DropMax", crystalDefinition.DefaultDropMax, "Maximum drop amount for " + crystalDefinition.PrefabName + ".");
				continue;
			}
			for (int j = 0; j < 4; j++)
			{
				string text2 = string.Empty;
				if (j == 0)
				{
					text2 = "Essence_Poison";
				}
				if (j == 1)
				{
					text2 = "Essence_Frost";
				}
				if (j == 2)
				{
					text2 = "Essence_Fire";
				}
				if (j == 3)
				{
					text2 = "Essence_Lightning";
				}
				crystalDefinition.RavenDropItems[j] = config.Bind<string>(text, "Drop" + (j + 1) + "Item", text2, "Drop item prefab for Raven drop slot " + (j + 1) + " on " + crystalDefinition.PrefabName + ". Leave blank to disable the slot.");
				crystalDefinition.RavenDropMins[j] = config.Bind<int>(text, "Drop" + (j + 1) + "Min", crystalDefinition.DefaultDropMin, "Minimum drop amount for Raven drop slot " + (j + 1) + " on " + crystalDefinition.PrefabName + ".");
				crystalDefinition.RavenDropMaxs[j] = config.Bind<int>(text, "Drop" + (j + 1) + "Max", crystalDefinition.DefaultDropMax, "Maximum drop amount for Raven drop slot " + (j + 1) + " on " + crystalDefinition.PrefabName + ".");
			}
		}
	}

	public static List<CrystalDropEntry> BuildDropEntries(CrystalDefinition crystal)
	{
		List<CrystalDropEntry> list = new List<CrystalDropEntry>();
		if (crystal == null)
		{
			return list;
		}
		if (crystal.IsRavenCrystal)
		{
			for (int i = 0; i < 4; i++)
			{
				string text = ((crystal.RavenDropItems[i] != null) ? crystal.RavenDropItems[i].Value : string.Empty);
				if (!string.IsNullOrWhiteSpace(text))
				{
					int num = ((crystal.RavenDropMins[i] != null) ? crystal.RavenDropMins[i].Value : crystal.DefaultDropMin);
					int num2 = ((crystal.RavenDropMaxs[i] != null) ? crystal.RavenDropMaxs[i].Value : crystal.DefaultDropMax);
					num = Mathf.Max(0, num);
					num2 = Mathf.Max(num, num2);
					list.Add(new CrystalDropEntry(text, num, num2));
				}
			}
			return list;
		}
		int num3 = ((crystal.DropMin != null) ? crystal.DropMin.Value : crystal.DefaultDropMin);
		int num4 = ((crystal.DropMax != null) ? crystal.DropMax.Value : crystal.DefaultDropMax);
		num3 = Mathf.Max(0, num3);
		num4 = Mathf.Max(num3, num4);
		string text2 = ((crystal.DropItem != null) ? crystal.DropItem.Value : crystal.DefaultDropItem);
		if (!string.IsNullOrWhiteSpace(text2))
		{
			list.Add(new CrystalDropEntry(text2, num3, num4));
		}
		return list;
	}

	public static CrystalDefinition FindCrystalDefinition(string prefabName)
	{
		for (int i = 0; i < CrystalDefinitions.Count; i++)
		{
			CrystalDefinition crystalDefinition = CrystalDefinitions[i];
			if (crystalDefinition != null && string.Equals(crystalDefinition.PrefabName, prefabName, StringComparison.Ordinal))
			{
				return crystalDefinition;
			}
		}
		return null;
	}
}
public sealed class CrystalDropEntry
{
	public string ItemName;

	public int Min;

	public int Max;

	public CrystalDropEntry(string itemName, int min, int max)
	{
		ItemName = itemName;
		Min = min;
		Max = max;
	}
}
public class CrystalHoverText : MonoBehaviour, Hoverable
{
	private string hoverName;

	private void Awake()
	{
		EnsureHoverName();
	}

	public void Configure(string prefabName)
	{
		hoverName = BuildHoverName(prefabName);
	}

	public string GetHoverText()
	{
		EnsureHoverName();
		string text = (string.IsNullOrWhiteSpace(hoverName) ? "Crystal" : hoverName);
		return text + "\n[<color=yellow><b>E</b></color>] Pick up";
	}

	public string GetHoverName()
	{
		EnsureHoverName();
		return string.IsNullOrWhiteSpace(hoverName) ? "Crystal" : hoverName;
	}

	private void EnsureHoverName()
	{
		if (string.IsNullOrWhiteSpace(hoverName))
		{
			string text = (((Object)(object)((Component)this).gameObject != (Object)null) ? ((Object)((Component)this).gameObject).name : string.Empty);
			if (!string.IsNullOrWhiteSpace(text) && text.EndsWith("(Clone)", StringComparison.OrdinalIgnoreCase))
			{
				text = text.Substring(0, text.Length - "(Clone)".Length).Trim();
			}
			hoverName = BuildHoverName(text);
		}
	}

	private static string BuildHoverName(string prefabName)
	{
		if (string.IsNullOrWhiteSpace(prefabName))
		{
			return "Crystal";
		}
		string[] array = prefabName.Split(new char[1] { '_' }, StringSplitOptions.RemoveEmptyEntries);
		if (array.Length == 0)
		{
			return "Crystal";
		}
		string text = "Medium";
		List<string> list = new List<string>();
		foreach (string text2 in array)
		{
			if (string.Equals(text2, "Small", StringComparison.OrdinalIgnoreCase))
			{
				text = "Small";
			}
			else if (string.Equals(text2, "Large", StringComparison.OrdinalIgnoreCase))
			{
				text = "Large";
			}
			else if (!string.Equals(text2, "Crystal", StringComparison.OrdinalIgnoreCase) && !string.Equals(text2, "Regrow", StringComparison.OrdinalIgnoreCase))
			{
				list.Add(UppercaseFirst(text2));
			}
		}
		if (list.Count == 0)
		{
			return text + " Crystal";
		}
		return text + " " + string.Join(" ", list.ToArray()) + " Crystal";
	}

	private static string UppercaseFirst(string value)
	{
		if (string.IsNullOrWhiteSpace(value))
		{
			return string.Empty;
		}
		if (value.Length == 1)
		{
			return value.ToUpperInvariant();
		}
		return char.ToUpperInvariant(value[0]) + value.Substring(1).ToLowerInvariant();
	}
}
public sealed class CrystalManager : MonoBehaviour
{
	private static readonly string[] RegrowPrefabNames = new string[5] { "Poison_Crystal_Regrow", "Frost_Crystal_Regrow", "Fire_Crystal_Regrow", "Lightning_Crystal_Regrow", "Raven_Crystal_Regrow" };

	private static CrystalManager instance;

	private static bool prefabsRegistered;

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

	public static void Initialize(BaseUnityPlugin plugin, AssetBundle bundle, ConfigFile config)
	{
		CrystalConfigFile.Initialize(config);
		if ((Object)(object)instance == (Object)null)
		{
			instance = ((Component)plugin).GetComponent<CrystalManager>();
			if ((Object)(object)instance == (Object)null)
			{
				instance = ((Component)plugin).gameObject.AddComponent<CrystalManager>();
			}
		}
	}

	public static void RegisterCrystalPrefabs(AssetBundle bundle)
	{
		//IL_010d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0117: Expected O, but got Unknown
		if (prefabsRegistered || (Object)(object)bundle == (Object)null)
		{
			return;
		}
		CrystalConfigFile.BuildCrystalDefinitions();
		int num = 0;
		int num2 = 0;
		int num3 = 0;
		int num4 = 0;
		IReadOnlyList<CrystalConfigFile.CrystalDefinition> definitions = CrystalConfigFile.Definitions;
		for (int i = 0; i < definitions.Count; i++)
		{
			CrystalConfigFile.CrystalDefinition crystalDefinition = definitions[i];
			GameObject val = bundle.LoadAsset<GameObject>(crystalDefinition.PrefabName);
			if ((Object)(object)val == (Object)null)
			{
				num2++;
				Debug.LogWarning((object)("Crystal prefab missing from asset bundle: " + crystalDefinition.PrefabName));
			}
			else
			{
				PrepareCrystalPrefab(val, crystalDefinition);
				RegisteredCrystalPrefabs[crystalDefinition.PrefabName] = val;
				num++;
			}
		}
		for (int j = 0; j < RegrowPrefabNames.Length; j++)
		{
			string text = RegrowPrefabNames[j];
			GameObject val2 = bundle.LoadAsset<GameObject>(text);
			if ((Object)(object)val2 == (Object)null)
			{
				num4++;
				Debug.LogWarning((object)("Crystal regrow prefab missing from asset bundle: " + text));
				continue;
			}
			PrepareRegrowPrefab(val2);
			PrefabManager.Instance.AddPrefab(new CustomPrefab(val2, true));
			RegisteredCrystalPrefabs[text] = val2;
			num3++;
		}
		prefabsRegistered = true;
		Debug.Log((object)("Crystal prefab preparation complete. Prepared crystals: " + num + ", Missing crystals: " + num2 + ", Regrow registered: " + num3 + ", Regrow missing: " + num4));
	}

	public static GameObject GetPreparedCrystalPrefab(string prefabName)
	{
		if (string.IsNullOrWhiteSpace(prefabName))
		{
			return null;
		}
		RegisteredCrystalPrefabs.TryGetValue(prefabName, out var value);
		return value;
	}

	private static void PrepareCrystalPrefab(GameObject prefab, CrystalConfigFile.CrystalDefinition crystal)
	{
		//IL_0130: 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_013c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0148: Expected O, but got Unknown
		//IL_0176: Unknown result type (might be due to invalid IL or missing references)
		//IL_017d: Expected O, but got Unknown
		//IL_015b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0160: Unknown result type (might be due to invalid IL or missing references)
		//IL_0168: Unknown result type (might be due to invalid IL or missing references)
		//IL_0174: Expected O, but got Unknown
		if (!((Object)(object)prefab == (Object)null) && crystal != null)
		{
			((Object)prefab).name = crystal.PrefabName;
			RemoveItemDrops(prefab);
			ZNetView val = prefab.GetComponent<ZNetView>();
			if ((Object)(object)val == (Object)null)
			{
				val = prefab.AddComponent<ZNetView>();
			}
			val.m_persistent = true;
			val.m_syncInitialScale = true;
			if (!Object.op_Implicit((Object)(object)prefab.GetComponent<ZSyncTransform>()))
			{
				prefab.AddComponent<ZSyncTransform>();
			}
			Piece val2 = prefab.GetComponent<Piece>();
			if ((Object)(object)val2 == (Object)null)
			{
				val2 = prefab.AddComponent<Piece>();
			}
			val2.m_groundOnly = false;
			val2.m_canBeRemoved = false;
			EnsureCollider(prefab);
			WearNTear val3 = prefab.GetComponent<WearNTear>();
			if ((Object)(object)val3 == (Object)null)
			{
				val3 = prefab.AddComponent<WearNTear>();
			}
			val3.m_health = ResolveDefaultHealth(crystal.PrefabName);
			val3.m_noRoofWear = true;
			GameObject val4 = null;
			GameObject val5 = null;
			if ((Object)(object)ZNetScene.instance != (Object)null)
			{
				val4 = ZNetScene.instance.GetPrefab("vfx_destroyed");
				val5 = ZNetScene.instance.GetPrefab("sfx_clay_pot_break");
			}
			List<EffectData> list = new List<EffectData>();
			if ((Object)(object)val4 != (Object)null)
			{
				list.Add(new EffectData
				{
					m_prefab = val4,
					m_enabled = true
				});
			}
			if ((Object)(object)val5 != (Object)null)
			{
				list.Add(new EffectData
				{
					m_prefab = val5,
					m_enabled = true
				});
			}
			EffectList val6 = new EffectList();
			val6.m_effectPrefabs = list.ToArray();
			val3.m_destroyedEffect = val6;
			CrystalRuntimeState crystalRuntimeState = prefab.GetComponent<CrystalRuntimeState>();
			if ((Object)(object)crystalRuntimeState == (Object)null)
			{
				crystalRuntimeState = prefab.AddComponent<CrystalRuntimeState>();
			}
			crystalRuntimeState.Configure(CrystalConfigFile.BuildDropEntries(crystal));
			CrystalHoverText crystalHoverText = prefab.GetComponent<CrystalHoverText>();
			if ((Object)(object)crystalHoverText == (Object)null)
			{
				crystalHoverText = prefab.AddComponent<CrystalHoverText>();
			}
			crystalHoverText.Configure(crystal.PrefabName);
			if (!Object.op_Implicit((Object)(object)prefab.GetComponent<CrystalBreakVisual>()))
			{
				prefab.AddComponent<CrystalBreakVisual>();
			}
		}
	}

	private static void PrepareRegrowPrefab(GameObject prefab)
	{
		if (!((Object)(object)prefab == (Object)null))
		{
			((Object)prefab).name = ((Object)prefab).name.Trim();
			RemoveItemDrops(prefab);
			RemovePickables(prefab);
			RemoveCrystalHoverText(prefab);
			ZNetView val = prefab.GetComponent<ZNetView>();
			if ((Object)(object)val == (Object)null)
			{
				val = prefab.AddComponent<ZNetView>();
			}
			val.m_persistent = true;
			val.m_syncInitialScale = true;
			if (!Object.op_Implicit((Object)(object)prefab.GetComponent<ZSyncTransform>()))
			{
				prefab.AddComponent<ZSyncTransform>();
			}
			Piece val2 = prefab.GetComponent<Piece>();
			if ((Object)(object)val2 == (Object)null)
			{
				val2 = prefab.AddComponent<Piece>();
			}
			val2.m_groundOnly = false;
			val2.m_canBeRemoved = false;
			EnsureCollider(prefab);
			WearNTear val3 = prefab.GetComponent<WearNTear>();
			if ((Object)(object)val3 == (Object)null)
			{
				val3 = prefab.AddComponent<WearNTear>();
			}
			val3.m_health = 1f;
			val3.m_noRoofWear = true;
			if ((Object)(object)prefab.GetComponent<CrystalRegrowTimer>() == (Object)null)
			{
				prefab.AddComponent<CrystalRegrowTimer>();
			}
		}
	}

	private static void EnsureCollider(GameObject prefab)
	{
		//IL_0061: 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_0073: 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_00ae: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)prefab == (Object)null || (Object)(object)prefab.GetComponentInChildren<Collider>(true) != (Object)null)
		{
			return;
		}
		BoxCollider val = prefab.GetComponent<BoxCollider>();
		if ((Object)(object)val == (Object)null)
		{
			val = prefab.AddComponent<BoxCollider>();
		}
		Renderer[] componentsInChildren = prefab.GetComponentsInChildren<Renderer>(true);
		if (componentsInChildren.Length != 0)
		{
			Bounds bounds = componentsInChildren[0].bounds;
			for (int i = 1; i < componentsInChildren.Length; i++)
			{
				((Bounds)(ref bounds)).Encapsulate(componentsInChildren[i].bounds);
			}
			val.center = prefab.transform.InverseTransformPoint(((Bounds)(ref bounds)).center);
			val.size = ((Bounds)(ref bounds)).size;
		}
	}

	private static float ResolveDefaultHealth(string prefabName)
	{
		if (string.IsNullOrWhiteSpace(prefabName))
		{
			return 200f;
		}
		if (prefabName.IndexOf("_Small", StringComparison.OrdinalIgnoreCase) >= 0)
		{
			return 100f;
		}
		if (prefabName.IndexOf("_Large", StringComparison.OrdinalIgnoreCase) >= 0)
		{
			return 300f;
		}
		return 200f;
	}

	private static void RemoveItemDrops(GameObject root)
	{
		if ((Object)(object)root == (Object)null)
		{
			return;
		}
		ItemDrop[] componentsInChildren = root.GetComponentsInChildren<ItemDrop>(true);
		for (int i = 0; i < componentsInChildren.Length; i++)
		{
			if ((Object)(object)componentsInChildren[i] != (Object)null)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren[i], true);
			}
		}
	}

	private static void RemovePickables(GameObject root)
	{
		if ((Object)(object)root == (Object)null)
		{
			return;
		}
		Pickable[] componentsInChildren = root.GetComponentsInChildren<Pickable>(true);
		for (int i = 0; i < componentsInChildren.Length; i++)
		{
			if ((Object)(object)componentsInChildren[i] != (Object)null)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren[i], true);
			}
		}
	}

	private static void RemoveCrystalHoverText(GameObject root)
	{
		if ((Object)(object)root == (Object)null)
		{
			return;
		}
		CrystalHoverText[] componentsInChildren = root.GetComponentsInChildren<CrystalHoverText>(true);
		for (int i = 0; i < componentsInChildren.Length; i++)
		{
			if ((Object)(object)componentsInChildren[i] != (Object)null)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren[i], true);
			}
		}
	}

	public static bool TryRestoreExistingCrystalState(CrystalRuntimeState runtime)
	{
		if ((Object)(object)runtime == (Object)null || (Object)(object)((Component)runtime).gameObject == (Object)null)
		{
			return false;
		}
		CrystalConfigFile.BuildCrystalDefinitions();
		string text = CleanPrefabName(((Object)((Component)runtime).gameObject).name);
		if (string.IsNullOrWhiteSpace(text))
		{
			return false;
		}
		CrystalConfigFile.CrystalDefinition crystalDefinition = CrystalConfigFile.FindCrystalDefinition(text);
		if (crystalDefinition == null)
		{
			return false;
		}
		runtime.Configure(CrystalConfigFile.BuildDropEntries(crystalDefinition));
		CrystalHoverText component = ((Component)runtime).GetComponent<CrystalHoverText>();
		if ((Object)(object)component != (Object)null)
		{
			component.Configure(crystalDefinition.PrefabName);
		}
		return true;
	}

	private static string CleanPrefabName(string prefabName)
	{
		if (string.IsNullOrWhiteSpace(prefabName))
		{
			return string.Empty;
		}
		string text = prefabName.Trim();
		if (text.EndsWith("(Clone)", StringComparison.OrdinalIgnoreCase))
		{
			text = text.Substring(0, text.Length - "(Clone)".Length).Trim();
		}
		return text;
	}
}
public class CrystalRegrowTimer : MonoBehaviour, Hoverable, Interactable
{
	[HarmonyPatch(typeof(Piece), "DropResources")]
	private static class Piece_DropResources_Patch
	{
		private static bool Prefix(Piece __instance)
		{
			if ((Object)(object)__instance == (Object)null)
			{
				return true;
			}
			CrystalRegrowTimer component = ((Component)__instance).GetComponent<CrystalRegrowTimer>();
			if ((Object)(object)component == (Object)null)
			{
				return true;
			}
			component.RequestSilentRemove();
			return false;
		}
	}

	[HarmonyPatch(typeof(WearNTear), "RPC_Damage")]
	private static class WearNTear_RPC_Damage_Patch
	{
		private static void Postfix(WearNTear __instance)
		{
			if (!((Object)(object)__instance == (Object)null))
			{
				CrystalRegrowTimer component = ((Component)__instance).GetComponent<CrystalRegrowTimer>();
				if (!((Object)(object)component == (Object)null) && !(__instance.m_health > 0f))
				{
					component.RequestSilentRemove();
				}
			}
		}
	}

	[CompilerGenerated]
	private sealed class <SilentRemoveRoutine>d__26 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		public CrystalRegrowTimer <>4__this;

		private float <timeout>5__1;

		private ZDO <zdo>5__2;

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

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

		[DebuggerHidden]
		public <SilentRemoveRoutine>d__26(int <>1__state)
		{
			this.<>1__state = <>1__state;
		}

		[DebuggerHidden]
		void IDisposable.Dispose()
		{
			<zdo>5__2 = null;
			<>1__state = -2;
		}

		private bool MoveNext()
		{
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Expected O, but got Unknown
			switch (<>1__state)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				<>4__this.removalInProgress = true;
				<timeout>5__1 = 1f;
				goto IL_0072;
			case 1:
				<>1__state = -1;
				goto IL_0072;
			case 2:
				{
					<>1__state = -1;
					<>4__this.DestroySelf();
					return false;
				}
				IL_0072:
				if (!<>4__this.TryClaimOwnership() && <timeout>5__1 > 0f)
				{
					<timeout>5__1 -= Time.deltaTime;
					<>2__current = null;
					<>1__state = 1;
					return true;
				}
				<zdo>5__2 = <>4__this.GetCarrierZdo();
				if (<zdo>5__2 != null && <>4__this.CanWriteZdo())
				{
					<zdo>5__2.Set("rwc_regrow_completed", 1);
					<zdo>5__2.Set("picked", 1);
				}
				<>4__this.PlayDestroyEffects();
				<>4__this.DisableInteraction();
				<>2__current = (object)new WaitForSeconds(0.05f);
				<>1__state = 2;
				return true;
			}
		}

		bool IEnumerator.MoveNext()
		{
			//ILSpy generated this explicit interface implementation from .override directive in MoveNext
			return this.MoveNext();
		}

		[DebuggerHidden]
		void IEnumerator.Reset()
		{
			throw new NotSupportedException();
		}
	}

	private const string CrystalRespawnerKey = "crystalRespawner";

	private const string PickedKey = "picked";

	private const string StartTicksZdoKey = "rwc_regrow_startticks";

	private const string DurationMinutesZdoKey = "rwc_regrow_durationminutes";

	private const string CompletedZdoKey = "rwc_regrow_completed";

	private const float DefaultRegrowMinutes = 1500f;

	private const float NearbyWorkbenchSuppressRadius = 20f;

	private const float NearbyBuildingSuppressRadius = 20f;

	private const string DestroyVfxPrefabName = "vfx_destroyed";

	private const string DestroySfxPrefabName = "sfx_clay_pot_break";

	private ZNetView znv;

	private Renderer[] cachedRenderers;

	private Collider[] cachedColliders;

	private float nextStateCheckTime;

	private bool removalInProgress;

	private void Awake()
	{
		znv = ((Component)this).GetComponent<ZNetView>();
		cachedRenderers = ((Component)this).GetComponentsInChildren<Renderer>(true);
		cachedColliders = ((Component)this).GetComponentsInChildren<Collider>(true);
		EnsureVisible();
		EnsureInitialized();
	}

	private void OnEnable()
	{
		EnsureVisible();
		EnsureInitialized();
	}

	private void LateUpdate()
	{
		EnsureVisible();
		if (!(Time.time < nextStateCheckTime))
		{
			nextStateCheckTime = Time.time + 1f;
			UpdateRespawnState();
		}
	}

	public string GetHoverName()
	{
		return BuildHoverName();
	}

	public string GetHoverText()
	{
		return BuildHoverText();
	}

	public bool Interact(Humanoid character, bool hold, bool alt)
	{
		return false;
	}

	public bool UseItem(Humanoid user, ItemData item)
	{
		return false;
	}

	public bool IsRegrowCarrier()
	{
		ZDO carrierZdo = GetCarrierZdo();
		if (carrierZdo == null)
		{
			return false;
		}
		return carrierZdo.GetInt("crystalRespawner", 0) == 1;
	}

	public string BuildHoverName()
	{
		string text = ResolveRespawnPrefabName();
		if (string.IsNullOrWhiteSpace(text))
		{
			return "Regrowing Crystal";
		}
		return BuildDisplayName(text) + " Regrowing";
	}

	public string BuildHoverText()
	{
		string text = BuildHoverName();
		double remainingSeconds = GetRemainingSeconds();
		if (remainingSeconds > 0.0)
		{
			return text + "\n<color=orange>Respawns in " + FormatRemaining(TimeSpan.FromSeconds(remainingSeconds)) + "</color>";
		}
		if (IsBlockedByNearbyBase())
		{
			return text + "\n<color=orange>Respawn blocked by nearby base/workbench</color>";
		}
		return text + "\n<color=orange>Respawning now...</color>";
	}

	public void RequestSilentRemove()
	{
		if (!removalInProgress)
		{
			((MonoBehaviour)this).StartCoroutine(SilentRemoveRoutine());
		}
	}

	[IteratorStateMachine(typeof(<SilentRemoveRoutine>d__26))]
	private IEnumerator SilentRemoveRoutine()
	{
		//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
		return new <SilentRemoveRoutine>d__26(0)
		{
			<>4__this = this
		};
	}

	private void PlayDestroyEffects()
	{
		//IL_0036: 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_0072: 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)
		if (!((Object)(object)ZNetScene.instance == (Object)null))
		{
			GameObject prefab = ZNetScene.instance.GetPrefab("vfx_destroyed");
			if ((Object)(object)prefab != (Object)null)
			{
				Object.Instantiate<GameObject>(prefab, ((Component)this).transform.position, ((Component)this).transform.rotation);
			}
			GameObject prefab2 = ZNetScene.instance.GetPrefab("sfx_clay_pot_break");
			if ((Object)(object)prefab2 != (Object)null)
			{
				Object.Instantiate<GameObject>(prefab2, ((Component)this).transform.position, ((Component)this).transform.rotation);
			}
		}
	}

	private void DisableInteraction()
	{
		if (cachedColliders == null || cachedColliders.Length == 0)
		{
			cachedColliders = ((Component)this).GetComponentsInChildren<Collider>(true);
		}
		for (int i = 0; i < cachedColliders.Length; i++)
		{
			if ((Object)(object)cachedColliders[i] != (Object)null)
			{
				cachedColliders[i].enabled = false;
			}
		}
	}

	private void DestroySelf()
	{
		if (!((Object)(object)((Component)this).gameObject == (Object)null))
		{
			if ((Object)(object)ZNetScene.instance != (Object)null)
			{
				ZNetScene.instance.Destroy(((Component)this).gameObject);
			}
			else
			{
				Object.Destroy((Object)(object)((Component)this).gameObject);
			}
		}
	}

	private void EnsureInitialized()
	{
		ZDO carrierZdo = GetCarrierZdo();
		if (carrierZdo == null)
		{
			return;
		}
		if (carrierZdo.GetLong("rwc_regrow_startticks", 0L) <= 0 && CanWriteZdo())
		{
			carrierZdo.Set("rwc_regrow_startticks", GetNetworkTime().Ticks);
		}
		if (carrierZdo.GetFloat("rwc_regrow_durationminutes", 0f) <= 0f && CanWriteZdo())
		{
			float num = carrierZdo.GetFloat("rwc_regrowminutes", 0f);
			if (num <= 0f)
			{
				num = carrierZdo.GetFloat("Pickable.m_respawnTimeMinutes", 0f);
			}
			if (num <= 0f)
			{
				num = carrierZdo.GetFloat("Pickable.m_respawnTimeInitMin", 0f);
			}
			if (num <= 0f)
			{
				num = 1500f;
			}
			carrierZdo.Set("rwc_regrow_durationminutes", num);
		}
		if (carrierZdo.GetInt("rwc_regrow_completed", 0) == 0 && GetRemainingSeconds(carrierZdo) > 0.0 && CanWriteZdo() && carrierZdo.GetInt("picked", 1) != 1)
		{
			carrierZdo.Set("picked", 1);
		}
	}

	private void UpdateRespawnState()
	{
		ZDO carrierZdo = GetCarrierZdo();
		if (carrierZdo == null || carrierZdo.GetInt("rwc_regrow_completed", 0) == 1)
		{
			return;
		}
		double remainingSeconds = GetRemainingSeconds(carrierZdo);
		if (remainingSeconds > 0.0)
		{
			if (CanWriteZdo() && carrierZdo.GetInt("picked", 1) != 1)
			{
				carrierZdo.Set("picked", 1);
			}
		}
		else if (IsBlockedByNearbyBase())
		{
			if (CanWriteZdo() && carrierZdo.GetInt("picked", 1) != 1)
			{
				carrierZdo.Set("picked", 1);
			}
		}
		else if (CanWriteZdo())
		{
			carrierZdo.Set("rwc_regrow_completed", 1);
			carrierZdo.Set("picked", 0);
		}
	}

	private void EnsureVisible()
	{
		if (!IsRegrowCarrier())
		{
			return;
		}
		if (cachedRenderers == null || cachedRenderers.Length == 0)
		{
			cachedRenderers = ((Component)this).GetComponentsInChildren<Renderer>(true);
		}
		if (cachedColliders == null || cachedColliders.Length == 0)
		{
			cachedColliders = ((Component)this).GetComponentsInChildren<Collider>(true);
		}
		for (int i = 0; i < cachedRenderers.Length; i++)
		{
			Renderer val = cachedRenderers[i];
			if (!((Object)(object)val == (Object)null))
			{
				if (!((Component)val).gameObject.activeSelf)
				{
					((Component)val).gameObject.SetActive(true);
				}
				val.enabled = true;
			}
		}
		for (int j = 0; j < cachedColliders.Length; j++)
		{
			Collider val2 = cachedColliders[j];
			if (!((Object)(object)val2 == (Object)null))
			{
				if (!((Component)val2).gameObject.activeSelf)
				{
					((Component)val2).gameObject.SetActive(true);
				}
				val2.enabled = true;
			}
		}
	}

	private bool IsBlockedByNearbyBase()
	{
		//IL_0017: 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_00c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_013c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0148: Unknown result type (might be due to invalid IL or missing references)
		float num = Mathf.Max(20f, 20f);
		Collider[] array = Physics.OverlapSphere(((Component)this).transform.position, num, -1, (QueryTriggerInteraction)2);
		if (array == null || array.Length == 0)
		{
			return false;
		}
		HashSet<int> hashSet = new HashSet<int>();
		foreach (Collider val in array)
		{
			if ((Object)(object)val == (Object)null)
			{
				continue;
			}
			CraftingStation componentInParent = ((Component)val).GetComponentInParent<CraftingStation>();
			if ((Object)(object)componentInParent != (Object)null)
			{
				int instanceID = ((Object)((Component)componentInParent).gameObject).GetInstanceID();
				if (hashSet.Add(instanceID) && (Object)(object)((Component)componentInParent).gameObject != (Object)(object)((Component)this).gameObject && Vector3.Distance(((Component)this).transform.position, ((Component)componentInParent).transform.position) <= 20f && HasPlayerCreator((Component)(object)componentInParent))
				{
					return true;
				}
			}
			Piece componentInParent2 = ((Component)val).GetComponentInParent<Piece>();
			if ((Object)(object)componentInParent2 != (Object)null)
			{
				int instanceID2 = ((Object)((Component)componentInParent2).gameObject).GetInstanceID();
				if (hashSet.Add(instanceID2) && (Object)(object)((Component)componentInParent2).gameObject != (Object)(object)((Component)this).gameObject && Vector3.Distance(((Component)this).transform.position, ((Component)componentInParent2).transform.position) <= 20f && HasPlayerCreator((Component)(object)componentInParent2))
				{
					return true;
				}
			}
		}
		return false;
	}

	private static bool HasPlayerCreator(Component component)
	{
		if ((Object)(object)component == (Object)null)
		{
			return false;
		}
		ZNetView val = component.GetComponent<ZNetView>();
		if ((Object)(object)val == (Object)null)
		{
			val = component.GetComponentInParent<ZNetView>();
		}
		if ((Object)(object)val == (Object)null || !val.IsValid())
		{
			return false;
		}
		ZDO zDO = val.GetZDO();
		if (zDO == null)
		{
			return false;
		}
		return zDO.GetLong(ZDOVars.s_creator, 0L) != 0;
	}

	private ZDO GetCarrierZdo()
	{
		znv = (((Object)(object)znv != (Object)null) ? znv : ((Component)this).GetComponent<ZNetView>());
		if ((Object)(object)znv == (Object)null || !znv.IsValid())
		{
			return null;
		}
		ZDO zDO = znv.GetZDO();
		if (zDO == null)
		{
			return null;
		}
		if (zDO.GetInt("crystalRespawner", 0) != 1)
		{
			return null;
		}
		return zDO;
	}

	private bool CanWriteZdo()
	{
		znv = (((Object)(object)znv != (Object)null) ? znv : ((Component)this).GetComponent<ZNetView>());
		if ((Object)(object)znv == (Object)null || !znv.IsValid())
		{
			return false;
		}
		if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer())
		{
			return true;
		}
		return znv.IsOwner();
	}

	private bool TryClaimOwnership()
	{
		znv = (((Object)(object)znv != (Object)null) ? znv : ((Component)this).GetComponent<ZNetView>());
		if ((Object)(object)znv == (Object)null || !znv.IsValid())
		{
			return true;
		}
		if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer())
		{
			return true;
		}
		if (!znv.IsOwner())
		{
			znv.ClaimOwnership();
		}
		return znv.IsOwner();
	}

	private double GetRemainingSeconds()
	{
		ZDO carrierZdo = GetCarrierZdo();
		if (carrierZdo == null)
		{
			return 0.0;
		}
		return GetRemainingSeconds(carrierZdo);
	}

	private double GetRemainingSeconds(ZDO zdo)
	{
		if (zdo == null)
		{
			return 0.0;
		}
		long @long = zdo.GetLong("rwc_regrow_startticks", 0L);
		float @float = zdo.GetFloat("rwc_regrow_durationminutes", 0f);
		if (@long <= 0 || @float <= 0f)
		{
			return 0.0;
		}
		DateTime dateTime = new DateTime(@long, DateTimeKind.Utc);
		DateTime networkTime = GetNetworkTime();
		double totalSeconds = (networkTime - dateTime).TotalSeconds;
		double num = (double)@float * 60.0;
		return Math.Max(0.0, num - totalSeconds);
	}

	private static DateTime GetNetworkTime()
	{
		if ((Object)(object)ZNet.instance != (Object)null)
		{
			return ZNet.instance.GetTime();
		}
		return DateTime.UtcNow;
	}

	private string ResolveRespawnPrefabName()
	{
		ZDO carrierZdo = GetCarrierZdo();
		if (carrierZdo != null)
		{
			string @string = carrierZdo.GetString("respawnprefab", string.Empty);
			if (!string.IsNullOrWhiteSpace(@string))
			{
				return @string;
			}
			@string = carrierZdo.GetString("rwc_respawnprefab", string.Empty);
			if (!string.IsNullOrWhiteSpace(@string))
			{
				return @string;
			}
		}
		string text = (((Object)(object)((Component)this).gameObject != (Object)null) ? ((Object)((Component)this).gameObject).name : string.Empty);
		if (text.EndsWith("(Clone)", StringComparison.OrdinalIgnoreCase))
		{
			text = text.Substring(0, text.Length - "(Clone)".Length).Trim();
		}
		if (text.EndsWith("_Regrow", StringComparison.OrdinalIgnoreCase))
		{
			text = text.Substring(0, text.Length - "_Regrow".Length).Trim();
		}
		return text;
	}

	private static string FormatRemaining(TimeSpan remaining)
	{
		int num = Mathf.Max(0, Mathf.CeilToInt((float)remaining.TotalSeconds));
		int num2 = num / 86400;
		int num3 = num % 86400 / 3600;
		int num4 = num % 3600 / 60;
		int num5 = num % 60;
		if (num2 > 0)
		{
			return num2 + "d " + num3 + "h " + num4 + "m";
		}
		if (num3 > 0)
		{
			return num3 + "h " + num4 + "m " + num5 + "s";
		}
		if (num4 > 0)
		{
			return num4 + "m " + num5 + "s";
		}
		return num5 + "s";
	}

	private static string BuildDisplayName(string prefabName)
	{
		if (string.IsNullOrWhiteSpace(prefabName))
		{
			return "Crystal";
		}
		string[] array = prefabName.Split(new char[1] { '_' }, StringSplitOptions.RemoveEmptyEntries);
		if (array.Length == 0)
		{
			return "Crystal";
		}
		string text = "Medium";
		List<string> list = new List<string>();
		foreach (string text2 in array)
		{
			if (string.Equals(text2, "Small", StringComparison.OrdinalIgnoreCase))
			{
				text = "Small";
			}
			else if (string.Equals(text2, "Large", StringComparison.OrdinalIgnoreCase))
			{
				text = "Large";
			}
			else if (!string.Equals(text2, "Crystal", StringComparison.OrdinalIgnoreCase) && !string.Equals(text2, "Regrow", StringComparison.OrdinalIgnoreCase))
			{
				list.Add(UppercaseFirst(text2));
			}
		}
		if (list.Count == 0)
		{
			return text + " Crystal";
		}
		return text + " " + string.Join(" ", list.ToArray()) + " Crystal";
	}

	private static string UppercaseFirst(string value)
	{
		if (string.IsNullOrWhiteSpace(value))
		{
			return string.Empty;
		}
		if (value.Length == 1)
		{
			return value.ToUpperInvariant();
		}
		return char.ToUpperInvariant(value[0]) + value.Substring(1).ToLowerInvariant();
	}
}
public class CrystalRuntimeState : MonoBehaviour, Interactable
{
	[HarmonyPatch(typeof(WearNTear), "RPC_Damage")]
	private static class WearNTear_RPC_Damage_Patch
	{
		private static void Postfix(WearNTear __instance)
		{
			if (!((Object)(object)__instance == (Object)null))
			{
				CrystalRuntimeState component = ((Component)__instance).GetComponent<CrystalRuntimeState>();
				if (!((Object)(object)component == (Object)null))
				{
					component.TryHandleDestroyed(fromOnDestroy: false);
				}
			}
		}
	}

	[HarmonyPatch(typeof(Piece), "SetCreator")]
	private static class Piece_SetCreator_Patch
	{
		private static void Postfix(Piece __instance)
		{
			if (!((Object)(object)__instance == (Object)null))
			{
				CrystalRuntimeState component = ((Component)__instance).GetComponent<CrystalRuntimeState>();
				if (!((Object)(object)component == (Object)null))
				{
					component.MarkPlayerPlaced();
					component.EnsurePieceRules();
				}
			}
		}
	}

	[HarmonyPatch(typeof(ObjectDB), "Awake")]
	private static class ObjectDB_Awake_Patch
	{
		private static void Postfix()
		{
			EnsureCultivatorRemoveEnabled();
		}
	}

	[HarmonyPatch(typeof(Player), "Awake")]
	private static class Player_Awake_Patch
	{
		private static void Postfix()
		{
			EnsureCultivatorRemoveEnabled();
		}
	}

	[HarmonyPatch(typeof(Player), "CheckCanRemovePiece")]
	private static class Player_CheckCanRemovePiece_Patch
	{
		private static bool Prefix(Player __instance, Piece piece, ref bool __result)
		{
			if (!IsManagedCrystalPiece(piece))
			{
				return true;
			}
			EnsureCultivatorRemoveEnabled();
			ItemData equippedRightItem = GetEquippedRightItem(__instance);
			if (!IsCultivator(equippedRightItem))
			{
				__result = false;
				return false;
			}
			bool flag = CanCultivatorRemovePiece(piece);
			if (!flag && (Object)(object)__instance != (Object)null)
			{
				((Character)__instance).Message((MessageType)2, "$msg_privatezone", 0, (Sprite)null);
			}
			__result = flag;
			return false;
		}
	}

	[HarmonyPatch(typeof(Player), "RemovePiece")]
	private static class Player_RemovePiece_Patch
	{
		private static bool Prefix(Player __instance)
		{
			EnsureCultivatorRemoveEnabled();
			ItemData equippedRightItem = GetEquippedRightItem(__instance);
			if (!IsCultivator(equippedRightItem))
			{
				return true;
			}
			if (!TryFindManagedPiece(__instance, out var targetPiece))
			{
				return true;
			}
			if (!CanCultivatorRemovePiece(targetPiece))
			{
				if ((Object)(object)__instance != (Object)null)
				{
					((Character)__instance).Message((MessageType)2, "$msg_privatezone", 0, (Sprite)null);
				}
				return false;
			}
			CrystalRuntimeState component = ((Component)targetPiece).GetComponent<CrystalRuntimeState>();
			if ((Object)(object)component != (Object)null)
			{
				component.RequestCultivatorMiddleMouseRemove();
				return false;
			}
			CrystalRegrowTimer component2 = ((Component)targetPiece).GetComponent<CrystalRegrowTimer>();
			if ((Object)(object)component2 != (Object)null)
			{
				component2.RequestSilentRemove();
				return false;
			}
			return true;
		}
	}

	[HarmonyPatch(typeof(Piece), "DropResources")]
	private static class Piece_DropResources_Patch
	{
		private static bool Prefix(Piece __instance)
		{
			if ((Object)(object)__instance == (Object)null)
			{
				return true;
			}
			CrystalRuntimeState component = ((Component)__instance).GetComponent<CrystalRuntimeState>();
			if ((Object)(object)component == (Object)null)
			{
				return true;
			}
			component.HandleToolRemove();
			return false;
		}
	}

	[CompilerGenerated]
	private sealed class <CultivatorRemoveRoutine>d__25 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		public CrystalRuntimeState <>4__this;

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

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

		[DebuggerHidden]
		public <CultivatorRemoveRoutine>d__25(int <>1__state)
		{
			this.<>1__state = <>1__state;
		}

		[DebuggerHidden]
		void IDisposable.Dispose()
		{
			<>1__state = -2;
		}

		private bool MoveNext()
		{
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Expected O, but got Unknown
			switch (<>1__state)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				<>4__this.pickupInProgress = true;
				<>4__this.suppressDropSpawn = true;
				<>4__this.handledDestroyed = true;
				<>4__this.breakVisual = (((Object)(object)<>4__this.breakVisual != (Object)null) ? <>4__this.breakVisual : ((Component)<>4__this).GetComponent<CrystalBreakVisual>());
				if ((Object)(object)<>4__this.breakVisual != (Object)null)
				{
					<>4__this.breakVisual.ForceBreak();
				}
				<>4__this.SpawnDrops();
				<>4__this.CreateDestroyedEffects();
				<>4__this.DisableInteraction();
				<>2__current = (object)new WaitForSeconds(0.32f);
				<>1__state = 1;
				return true;
			case 1:
				<>1__state = -1;
				<>4__this.DestroySelf();
				return false;
			}
		}

		bool IEnumerator.MoveNext()
		{
			//ILSpy generated this explicit interface implementation from .override directive in MoveNext
			return this.MoveNext();
		}

		[DebuggerHidden]
		void IEnumerator.Reset()
		{
			throw new NotSupportedException();
		}
	}

	[CompilerGenerated]
	private sealed class <PickupRoutine>d__24 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		public CrystalRuntimeState <>4__this;

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

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

		[DebuggerHidden]
		public <PickupRoutine>d__24(int <>1__state)
		{
			this.<>1__state = <>1__state;
		}

		[DebuggerHidden]
		void IDisposable.Dispose()
		{
			<>1__state = -2;
		}

		private bool MoveNext()
		{
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Expected O, but got Unknown
			switch (<>1__state)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				<>4__this.pickupInProgress = true;
				<>4__this.suppressDropSpawn = true;
				<>4__this.handledDestroyed = true;
				<>4__this.breakVisual = (((Object)(object)<>4__this.breakVisual != (Object)null) ? <>4__this.breakVisual : ((Component)<>4__this).GetComponent<CrystalBreakVisual>());
				if ((Object)(object)<>4__this.breakVisual != (Object)null)
				{
					<>4__this.breakVisual.ForceBreak();
				}
				<>4__this.SpawnDrops();
				<>4__this.CreateDestroyedEffects();
				<>4__this.DisableInteraction();
				<>2__current = (object)new WaitForSeconds(0.32f);
				<>1__state = 1;
				return true;
			case 1:
				<>1__state = -1;
				<>4__this.DestroySelf();
				return false;
			}
		}

		bool IEnumerator.MoveNext()
		{
			//ILSpy generated this explicit interface implementation from .override directive in MoveNext
			return this.MoveNext();
		}

		[DebuggerHidden]
		void IEnumerator.Reset()
		{
			throw new NotSupportedException();
		}
	}

	private const string PlayerPlacedZdoKey = "rwc_playerplaced";

	private const string CultivatorPrefabName = "Cultivator";

	private const float RemoveRayDistance = 50f;

	private static readonly FieldInfo RightItemField = AccessTools.Field(typeof(Humanoid), "m_rightItem");

	private static readonly MethodInfo GetRightItemMethod = AccessTools.Method(typeof(Humanoid), "GetRightItem", (Type[])null, (Type[])null);

	private static readonly int RemoveRayMask = LayerMask.GetMask(new string[5] { "piece", "piece_nonsolid", "item", "Default_small", "Default" });

	private readonly List<CrystalDropEntry> dropEntries = new List<CrystalDropEntry>();

	private bool handledDestroyed;

	private bool restoredExistingState;

	private bool suppressDropSpawn;

	private bool pickupInProgress;

	private WearNTear wear;

	private ZNetView znv;

	private CrystalBreakVisual breakVisual;

	private Piece piece;

	public void Configure(List<CrystalDropEntry> entries)
	{
		dropEntries.Clear();
		if (entries == null)
		{
			return;
		}
		for (int i = 0; i < entries.Count; i++)
		{
			CrystalDropEntry crystalDropEntry = entries[i];
			if (crystalDropEntry != null)
			{
				dropEntries.Add(new CrystalDropEntry(crystalDropEntry.ItemName, crystalDropEntry.Min, crystalDropEntry.Max));
			}
		}
	}

	public void MarkPlayerPlaced()
	{
		znv = (((Object)(object)znv != (Object)null) ? znv : ((Component)this).GetComponent<ZNetView>());
		if (!((Object)(object)znv == (Object)null) && znv.IsValid())
		{
			ZDO zDO = znv.GetZDO();
			if (zDO != null)
			{
				zDO.Set("rwc_playerplaced", 1);
			}
		}
	}

	public bool IsPlayerPlaced()
	{
		znv = (((Object)(object)znv != (Object)null) ? znv : ((Component)this).GetComponent<ZNetView>());
		if ((Object)(object)znv == (Object)null || !znv.IsValid())
		{
			return false;
		}
		ZDO zDO = znv.GetZDO();
		if (zDO == null)
		{
			return false;
		}
		return zDO.GetInt("rwc_playerplaced", 0) == 1;
	}

	public bool Interact(Humanoid character, bool hold, bool alt)
	{
		if (hold)
		{
			return false;
		}
		if (pickupInProgress || handledDestroyed)
		{
			return true;
		}
		if (!TryClaimOwnership())
		{
			return true;
		}
		((MonoBehaviour)this).StartCoroutine(PickupRoutine());
		return true;
	}

	public bool UseItem(Humanoid user, ItemData item)
	{
		return false;
	}

	public void RequestCultivatorMiddleMouseRemove()
	{
		if (!pickupInProgress && !handledDestroyed && TryClaimOwnership())
		{
			((MonoBehaviour)this).StartCoroutine(CultivatorRemoveRoutine());
		}
	}

	public void HandleToolRemove()
	{
		if (handledDestroyed)
		{
			suppressDropSpawn = true;
			return;
		}
		suppressDropSpawn = true;
		handledDestroyed = true;
		breakVisual = (((Object)(object)breakVisual != (Object)null) ? breakVisual : ((Component)this).GetComponent<CrystalBreakVisual>());
		if ((Object)(object)breakVisual != (Object)null)
		{
			breakVisual.ForceBreakImmediate();
		}
		SpawnDrops();
		CreateDestroyedEffects();
	}

	private void Awake()
	{
		wear = ((Component)this).GetComponent<WearNTear>();
		znv = ((Component)this).GetComponent<ZNetView>();
		breakVisual = ((Component)this).GetComponent<CrystalBreakVisual>();
		piece = ((Component)this).GetComponent<Piece>();
		EnsurePieceRules();
		TryRestoreExistingState();
	}

	private void OnDestroy()
	{
		TryHandleDestroyed(fromOnDestroy: true);
	}

	[IteratorStateMachine(typeof(<PickupRoutine>d__24))]
	private IEnumerator PickupRoutine()
	{
		//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
		return new <PickupRoutine>d__24(0)
		{
			<>4__this = this
		};
	}

	[IteratorStateMachine(typeof(<CultivatorRemoveRoutine>d__25))]
	private IEnumerator CultivatorRemoveRoutine()
	{
		//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
		return new <CultivatorRemoveRoutine>d__25(0)
		{
			<>4__this = this
		};
	}

	private void DisableInteraction()
	{
		Collider[] componentsInChildren = ((Component)this).GetComponentsInChildren<Collider>(true);
		for (int i = 0; i < componentsInChildren.Length; i++)
		{
			if ((Object)(object)componentsInChildren[i] != (Object)null)
			{
				componentsInChildren[i].enabled = false;
			}
		}
	}

	private void DestroySelf()
	{
		if (!((Object)(object)((Component)this).gameObject == (Object)null))
		{
			if ((Object)(object)ZNetScene.instance != (Object)null)
			{
				ZNetScene.instance.Destroy(((Component)this).gameObject);
			}
			else
			{
				Object.Destroy((Object)(object)((Component)this).gameObject);
			}
		}
	}

	private void EnsurePieceRules()
	{
		piece = (((Object)(object)piece != (Object)null) ? piece : ((Component)this).GetComponent<Piece>());
		if (!((Object)(object)piece == (Object)null))
		{
			piece.m_groundOnly = false;
			piece.m_canBeRemoved = false;
		}
	}

	private void TryRestoreExistingState()
	{
		if (!restoredExistingState)
		{
			restoredExistingState = CrystalManager.TryRestoreExistingCrystalState(this);
			EnsurePieceRules();
		}
	}

	private bool TryClaimOwnership()
	{
		znv = (((Object)(object)znv != (Object)null) ? znv : ((Component)this).GetComponent<ZNetView>());
		if ((Object)(object)znv == (Object)null || !znv.IsValid())
		{
			return true;
		}
		if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer())
		{
			return true;
		}
		if (!znv.IsOwner())
		{
			znv.ClaimOwnership();
		}
		return znv.IsOwner();
	}

	private bool CanHandleDestroyedState()
	{
		znv = (((Object)(object)znv != (Object)null) ? znv : ((Component)this).GetComponent<ZNetView>());
		if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer())
		{
			return true;
		}
		if ((Object)(object)znv == (Object)null)
		{
			return true;
		}
		return !znv.IsValid() || znv.IsOwner();
	}

	private void TryHandleDestroyed(bool fromOnDestroy)
	{
		if (handledDestroyed)
		{
			return;
		}
		if (suppressDropSpawn)
		{
			handledDestroyed = true;
		}
		else
		{
			if (!CanHandleDestroyedState())
			{
				return;
			}
			wear = (((Object)(object)wear != (Object)null) ? wear : ((Component)this).GetComponent<WearNTear>());
			if ((Object)(object)wear == (Object)null)
			{
				if (fromOnDestroy)
				{
				}
			}
			else if (!(wear.m_health > 0f))
			{
				handledDestroyed = true;
				SpawnDrops();
			}
		}
	}

	private void CreateDestroyedEffects()
	{
		//IL_00a0: 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)
		wear = (((Object)(object)wear != (Object)null) ? wear : ((Component)this).GetComponent<WearNTear>());
		if ((Object)(object)wear == (Object)null || wear.m_destroyedEffect == null || wear.m_destroyedEffect.m_effectPrefabs == null)
		{
			return;
		}
		for (int i = 0; i < wear.m_destroyedEffect.m_effectPrefabs.Length; i++)
		{
			EffectData val = wear.m_destroyedEffect.m_effectPrefabs[i];
			if (val != null && val.m_enabled && !((Object)(object)val.m_prefab == (Object)null))
			{
				Object.Instantiate<GameObject>(val.m_prefab, ((Component)this).transform.position, ((Component)this).transform.rotation);
			}
		}
	}

	private void SpawnDrops()
	{
		//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00da: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e4: 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_00f2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
		//IL_011a: Unknown result type (might be due to invalid IL or missing references)
		//IL_011c: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)ZNetScene.instance == (Object)null || dropEntries.Count == 0)
		{
			return;
		}
		for (int i = 0; i < dropEntries.Count; i++)
		{
			CrystalDropEntry crystalDropEntry = dropEntries[i];
			if (crystalDropEntry == null || string.IsNullOrWhiteSpace(crystalDropEntry.ItemName))
			{
				continue;
			}
			GameObject prefab = ZNetScene.instance.GetPrefab(crystalDropEntry.ItemName);
			if ((Object)(object)prefab == (Object)null)
			{
				Debug.LogWarning((object)("Crystal drop prefab not found: " + crystalDropEntry.ItemName));
				continue;
			}
			int num = Mathf.Max(0, crystalDropEntry.Min);
			int num2 = Mathf.Max(num, crystalDropEntry.Max);
			int num3 = Random.Range(num, num2 + 1);
			for (int j = 0; j < num3; j++)
			{
				Vector3 val = ((Component)this).transform.position + Vector3.up + Random.insideUnitSphere * 0.15f;
				val.y = Mathf.Max(val.y, ((Component)this).transform.position.y + 0.5f);
				Object.Instantiate<GameObject>(prefab, val, Quaternion.identity);
			}
		}
	}

	private static bool IsCultivator(ItemData item)
	{
		if (item == null)
		{
			return false;
		}
		if ((Object)(object)item.m_dropPrefab != (Object)null)
		{
			string a = CleanPrefabName(((Object)item.m_dropPrefab).name);
			if (string.Equals(a, "Cultivator", StringComparison.Ordinal))
			{
				return true;
			}
		}
		if (item.m_shared != null && (string.Equals(item.m_shared.m_name, "$item_cultivator", StringComparison.Ordinal) || string.Equals(item.m_shared.m_name, "Cultivator", StringComparison.Ordinal)))
		{
			return true;
		}
		return false;
	}

	private static ItemData GetEquippedRightItem(Player player)
	{
		if ((Object)(object)player == (Object)null)
		{
			return null;
		}
		if (RightItemField != null)
		{
			try
			{
				object? value = RightItemField.GetValue(player);
				return (ItemData)((value is ItemData) ? value : null);
			}
			catch
			{
			}
		}
		if (GetRightItemMethod != null)
		{
			try
			{
				object? obj2 = GetRightItemMethod.Invoke(player, null);
				return (ItemData)((obj2 is ItemData) ? obj2 : null);
			}
			catch
			{
			}
		}
		return null;
	}

	private static bool IsManagedCrystalPiece(Piece targetPiece)
	{
		if ((Object)(object)targetPiece == (Object)null)
		{
			return false;
		}
		return (Object)(object)((Component)targetPiece).GetComponent<CrystalRuntimeState>() != (Object)null || (Object)(object)((Component)targetPiece).GetComponent<CrystalRegrowTimer>() != (Object)null;
	}

	private static bool CanCultivatorRemovePiece(Piece targetPiece)
	{
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		if (!IsManagedCrystalPiece(targetPiece))
		{
			return false;
		}
		return PrivateArea.CheckAccess(((Component)targetPiece).transform.position, 0f, true, false);
	}

	private static void EnsureCultivatorRemoveEnabled()
	{
		ObjectDB instance = ObjectDB.instance;
		if ((Object)(object)instance == (Object)null)
		{
			return;
		}
		GameObject itemPrefab = instance.GetItemPrefab("Cultivator");
		if ((Object)(object)itemPrefab == (Object)null)
		{
			return;
		}
		ItemDrop component = itemPrefab.GetComponent<ItemDrop>();
		if (!((Object)(object)component == (Object)null) && component.m_itemData != null && component.m_itemData.m_shared != null)
		{
			PieceTable buildPieces = component.m_itemData.m_shared.m_buildPieces;
			if (!((Object)(object)buildPieces == (Object)null))
			{
				buildPieces.m_canRemovePieces = true;
			}
		}
	}

	private static bool TryFindManagedPiece(Player player, out Piece targetPiece)
	{
		//IL_0045: 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_0071: Unknown result type (might be due to invalid IL or missing references)
		//IL_007c: Unknown result type (might be due to invalid IL or missing references)
		targetPiece = null;
		if ((Object)(object)player == (Object)null || (Object)(object)GameCamera.instance == (Object)null)
		{
			return false;
		}
		Transform transform = ((Component)GameCamera.instance).transform;
		if ((Object)(object)transform == (Object)null)
		{
			return false;
		}
		RaycastHit val = default(RaycastHit);
		if (!Physics.Raycast(transform.position, transform.forward, ref val, 50f, RemoveRayMask))
		{
			return false;
		}
		if (Vector3.Distance(((RaycastHit)(ref val)).point, ((Character)player).m_eye.position) > player.m_maxPlaceDistance)
		{
			return false;
		}
		targetPiece = (((Object)(object)((RaycastHit)(ref val)).collider != (Object)null) ? ((Component)((RaycastHit)(ref val)).collider).GetComponentInParent<Piece>() : null);
		return IsManagedCrystalPiece(targetPiece);
	}

	private static string CleanPrefabName(string prefabName)
	{
		if (string.IsNullOrWhiteSpace(prefabName))
		{
			return string.Empty;
		}
		string text = prefabName.Trim();
		if (text.EndsWith("(Clone)", StringComparison.OrdinalIgnoreCase))
		{
			text = text.Substring(0, text.Length - "(Clone)".Length).Trim();
		}
		return text;
	}
}
public class LocalizeKey : MonoBehaviour
{
	public string Key;

	public void Awake()
	{
		if (!string.IsNullOrEmpty(Key))
		{
			string text = LocalizationCache.Get(Key);
		}
	}
}
public static class Localizer
{
	public static void Add(string key, string value)
	{
		LocalizationCache.Add(key, value);
	}

	public static void Register()
	{
		LocalizationCache.RegisterToJotunnLocalization();
	}
}
public class PlacementWatcher : MonoBehaviour
{
	public List<GameObject> RegisterList;

	private void Start()
	{
		if (RegisterList != null && !RegisterList.Contains(((Component)this).gameObject))
		{
			RegisterList.Add(((Component)this).gameObject);
		}
	}

	private void OnDestroy()
	{
		if (RegisterList != null)
		{
			RegisterList.Remove(((Component)this).gameObject);
		}
	}
}
public static class LocalizationCache
{
	private static Dictionary<string, string> translations = new Dictionary<string, string>();

	public static void Add(string key, string value)
	{
		translations[key] = value;
	}

	public static string Get(string key, string fallback = null)
	{
		if (translations.TryGetValue(key, out var value))
		{
			return value;
		}
		return fallback ?? key;
	}

	public static void RegisterToJotunnLocalization()
	{
		CustomLocalization localization = LocalizationManager.Instance.GetLocalization();
		foreach (KeyValuePair<string, string> translation in translations)
		{
			string text = "English";
			string key = translation.Key;
			localization.AddTranslation(ref text, ref key, translation.Value);
		}
	}
}
[BepInPlugin("Ravenwood.Crystals", "Ravenwood Crystals", "1.0.1")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class RavenwoodCrystals : BaseUnityPlugin
{
	[CompilerGenerated]
	private sealed class <DelayedRegister>d__10 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		public AssetBundle bundle;

		public RavenwoodCrystals <>4__this;

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

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

		[DebuggerHidden]
		public <DelayedRegister>d__10(int <>1__state)
		{
			this.<>1__state = <>1__state;
		}

		[DebuggerHidden]
		void IDisposable.Dispose()
		{
			<>1__state = -2;
		}

		private bool MoveNext()
		{
			switch (<>1__state)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				break;
			case 1:
				<>1__state = -1;
				break;
			}
			if ((Object)(object)ZNetScene.instance == (Object)null)
			{
				<>2__current = null;
				<>1__state = 1;
				return true;
			}
			RelicRegistrar.RegisterAllRelics(bundle);
			return false;
		}

		bool IEnumerator.MoveNext()
		{
			//ILSpy generated this explicit interface implementation from .override directive in MoveNext
			return this.MoveNext();
		}

		[DebuggerHidden]
		void IEnumerator.Reset()
		{
			throw new NotSupportedException();
		}
	}

	public const string PluginGUID = "Ravenwood.Crystals";

	public const string PluginName = "Ravenwood Crystals";

	public const string PluginVersion = "1.0.1";

	private const string PreferredCategoryName = "RavenCrystals";

	private AssetBundle gatesBundle;

	private static readonly List<GameObject> placedObjects = new List<GameObject>();

	public static string GetPreferredCategoryName()
	{
		return "RavenCrystals";
	}

	private void Awake()
	{
		//IL_0006: 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)
		new Harmony("ravenwood.crystals").PatchAll();
		gatesBundle = EmbeddedAssetBundleLoader.LoadBundle("RavenwoodCrystals.ravenwoodcrystals");
		if ((Object)(object)gatesBundle == (Object)null)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"Failed to load embedded AssetBundle.");
			return;
		}
		TrackAllPrefabsInBundle(gatesBundle);
		foreach (string allCategory in RelicRegistrar.GetAllCategories())
		{
			PieceManager.Instance.AddPieceCategory(allCategory);
		}
		CrystalManager.Initialize((BaseUnityPlugin)(object)this, gatesBundle, ((BaseUnityPlugin)this).Config);
		CrystalManager.RegisterCrystalPrefabs(gatesBundle);
		PrefabManager.OnPrefabsRegistered += OnPrefabsRegistered;
	}

	private void OnDestroy()
	{
		PrefabManager.OnPrefabsRegistered -= OnPrefabsRegistered;
	}

	private void OnPrefabsRegistered()
	{
		((MonoBehaviour)this).StartCoroutine(DelayedRegister(gatesBundle));
	}

	[IteratorStateMachine(typeof(<DelayedRegister>d__10))]
	private IEnumerator DelayedRegister(AssetBundle bundle)
	{
		//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
		return new <DelayedRegister>d__10(0)
		{
			<>4__this = this,
			bundle = bundle
		};
	}

	public static void TrackAllPrefabsInBundle(AssetBundle bundle)
	{
		GameObject[] array = bundle.LoadAllAssets<GameObject>();
		foreach (GameObject val in array)
		{
			if ((Object)(object)val != (Object)null && (Object)(object)val.GetComponent<PlacementWatcher>() == (Object)null)
			{
				val.AddComponent<PlacementWatcher>().RegisterList = placedObjects;
			}
		}
	}
}
public static class EmbeddedAssetBundleLoader
{
	public static AssetBundle LoadBundle(string resourcePath)
	{
		Assembly executingAssembly = Assembly.GetExecutingAssembly();
		using Stream stream = executingAssembly.GetManifestResourceStream(resourcePath);
		if (stream == null)
		{
			Debug.LogError((object)("AssetBundle resource not found: " + resourcePath));
			return null;
		}
		byte[] array = new byte[stream.Length];
		stream.Read(array, 0, array.Length);
		return AssetBundle.LoadFromMemory(array);
	}
}
public class RelicRegistration
{
	public string PrefabName;

	public string DisplayName;

	public RequirementConfig[] Requirements;

	public string Description;

	public string Category;

	public int Comfort;

	public string CraftingStation;

	public string PieceTable;

	public RelicRegistration(string prefab, string display, RequirementConfig[] reqs, string desc, string cat, string pieceTable = "_CultivatorPieceTable", int comfort = 0, string craftingStation = "")
	{
		PrefabName = prefab;
		DisplayName = display;
		Requirements = reqs;
		Description = desc;
		Category = cat;
		PieceTable = pieceTable;
		Comfort = comfort;
		CraftingStation = craftingStation;
	}
}
public static class RelicRegistrar
{
	private static bool wasAlreadyRegistered = false;

	public static readonly List<RelicRegistration> AllRegistrations = new List<RelicRegistration>
	{
		CreateElementCrystal("Poison_Crystal_Small", "Small Poison Crystal", "Essence_Poison", 50),
		CreateElementCrystal("Poison_Crystal", "Medium Poison Crystal", "Essence_Poison", 100),
		CreateElementCrystal("Poison_Crystal_Large", "Large Poison Crystal", "Essence_Poison", 200),
		CreateElementCrystal("Frost_Crystal_Small", "Small Frost Crystal", "Essence_Frost", 50),
		CreateElementCrystal("Frost_Crystal", "Medium Frost Crystal", "Essence_Frost", 100),
		CreateElementCrystal("Frost_Crystal_Large", "Large Frost Crystal", "Essence_Frost", 200),
		CreateElementCrystal("Fire_Crystal_Small", "Small Fire Crystal", "Essence_Fire", 50),
		CreateElementCrystal("Fire_Crystal", "Medium Fire Crystal", "Essence_Fire", 100),
		CreateElementCrystal("Fire_Crystal_Large", "Large Fire Crystal", "Essence_Fire", 200),
		CreateElementCrystal("Lightning_Crystal_Small", "Small Lightning Crystal", "Essence_Lightning", 50),
		CreateElementCrystal("Lightning_Crystal", "Medium Lightning Crystal", "Essence_Lightning", 100),
		CreateElementCrystal("Lightning_Crystal_Large", "Large Lightning Crystal", "Essence_Lightning", 200),
		CreateRavenCrystal("Raven_Crystal_Small", "Small Raven Crystal", 33, 33, 33, 33),
		CreateRavenCrystal("Raven_Crystal", "Medium Raven Crystal", 50, 50, 50, 50),
		CreateRavenCrystal("Raven_Crystal_Large", "Large Raven Crystal", 100, 100, 100, 100)
	};

	public static IEnumerable<string> GetAllCategories()
	{
		return AllRegistrations.Select((RelicRegistration r) => CategoryToTab(r.Category)).Distinct();
	}

	private static string CategoryToTab(string category)
	{
		if (string.IsNullOrWhiteSpace(category))
		{
			return RavenwoodCrystals.GetPreferredCategoryName();
		}
		switch (category.ToLowerInvariant())
		{
		case "building":
		case "cultivator":
		case "ravenwoodcrystals":
		case "ravenwoodcrysta":
		case "raven crystals":
		case "ravencrystals":
			return RavenwoodCrystals.GetPreferredCategoryName();
		default:
			return category;
		}
	}

	public static void RegisterAllRelics(AssetBundle bundle)
	{
		if (wasAlreadyRegistered)
		{
			return;
		}
		foreach (RelicRegistration allRegistration in AllRegistrations)
		{
			RegisterRelic(bundle, allRegistration);
		}
		wasAlreadyRegistered = true;
	}

	private static void RegisterRelic(AssetBundle bundle, RelicRegistration reg)
	{
		//IL_0158: Unknown result type (might be due to invalid IL or missing references)
		//IL_015d: 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_0170: Expected O, but got Unknown
		//IL_019e: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a5: Expected O, but got Unknown
		//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_019c: Expected O, but got Unknown
		//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0200: Unknown result type (might be due to invalid IL or missing references)
		//IL_0208: Unknown result type (might be due to invalid IL or missing references)
		//IL_0214: Expected O, but got Unknown
		//IL_0242: Unknown result type (might be due to invalid IL or missing references)
		//IL_0249: Expected O, but got Unknown
		//IL_0227: Unknown result type (might be due to invalid IL or missing references)
		//IL_022c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0234: Unknown result type (might be due to invalid IL or missing references)
		//IL_0240: Expected O, but got Unknown
		//IL_0286: Unknown result type (might be due to invalid IL or missing references)
		//IL_028d: Expected O, but got Unknown
		//IL_02d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_02dd: Expected O, but got Unknown
		GameObject val = CrystalManager.GetPreparedCrystalPrefab(reg.PrefabName);
		if ((Object)(object)val == (Object)null && (Object)(object)bundle != (Object)null)
		{
			val = bundle.LoadAsset<GameObject>(reg.PrefabName);
		}
		if (!((Object)(object)val == (Object)null))
		{
			((Object)val).name = reg.PrefabName;
			ZNetView val2 = val.GetComponent<ZNetView>();
			if ((Object)(object)val2 == (Object)null)
			{
				val2 = val.AddComponent<ZNetView>();
			}
			val2.m_persistent = true;
			val2.m_syncInitialScale = true;
			if (!Object.op_Implicit((Object)(object)val.GetComponent<ZSyncTransform>()))
			{
				val.AddComponent<ZSyncTransform>();
			}
			Piece val3 = val.GetComponent<Piece>();
			if ((Object)(object)val3 == (Object)null)
			{
				val3 = val.AddComponent<Piece>();
			}
			val3.m_name = reg.DisplayName;
			val3.m_description = reg.Description;
			val3.m_groundOnly = false;
			val3.m_canBeRemoved = false;
			GameObject val4 = null;
			GameObject val5 = null;
			GameObject val6 = null;
			GameObject val7 = null;
			if ((Object)(object)ZNetScene.instance != (Object)null)
			{
				val4 = ZNetScene.instance.GetPrefab("vfx_Place_stone");
				val5 = ZNetScene.instance.GetPrefab("sfx_build_hammer_stone");
				val6 = ZNetScene.instance.GetPrefab("vfx_destroyed");
				val7 = ZNetScene.instance.GetPrefab("sfx_clay_pot_break");
			}
			List<EffectData> list = new List<EffectData>();
			if ((Object)(object)val4 != (Object)null)
			{
				list.Add(new EffectData
				{
					m_prefab = val4,
					m_enabled = true
				});
			}
			if ((Object)(object)val5 != (Object)null)
			{
				list.Add(new EffectData
				{
					m_prefab = val5,
					m_enabled = true
				});
			}
			EffectList val8 = new EffectList();
			val8.m_effectPrefabs = list.ToArray();
			val3.m_placeEffect = val8;
			WearNTear val9 = val.GetComponent<WearNTear>();
			if ((Object)(object)val9 == (Object)null)
			{
				val9 = val.AddComponent<WearNTear>();
			}
			val9.m_noRoofWear = true;
			List<EffectData> list2 = new List<EffectData>();
			if ((Object)(object)val6 != (Object)null)
			{
				list2.Add(new EffectData
				{
					m_prefab = val6,
					m_enabled = true
				});
			}
			if ((Object)(object)val7 != (Object)null)
			{
				list2.Add(new EffectData
				{
					m_prefab = val7,
					m_enabled = true
				});
			}
			EffectList val10 = new EffectList();
			val10.m_effectPrefabs = list2.ToArray();
			val9.m_destroyedEffect = val10;
			Sprite val11 = ResolveCrystalIcon(bundle, reg.PrefabName);
			if ((Object)(object)val11 != (Object)null)
			{
				val3.m_icon = val11;
			}
			PieceConfig val12 = new PieceConfig();
			val12.PieceTable = reg.PieceTable;
			val12.Category = CategoryToTab(reg.Category);
			val12.CraftingStation = reg.CraftingStation;
			val12.Requirements = reg.Requirements;
			PieceManager.Instance.AddPiece(new CustomPiece(val, true, val12));
		}
	}

	private static Sprite ResolveCrystalIcon(AssetBundle bundle, string prefabName)
	{
		if ((Object)(object)bundle == (Object)null || string.IsNullOrWhiteSpace(prefabName))
		{
			return null;
		}
		Sprite val = bundle.LoadAsset<Sprite>(prefabName);
		if ((Object)(object)val != (Object)null)
		{
			return val;
		}
		val = bundle.LoadAsset<Sprite>(prefabName.ToLowerInvariant());
		if ((Object)(object)val != (Object)null)
		{
			return val;
		}
		string[] array = BuildIconFallbacks(prefabName);
		foreach (string text in array)
		{
			if (!string.IsNullOrWhiteSpace(text))
			{
				val = bundle.LoadAsset<Sprite>(text);
				if ((Object)(object)val != (Object)null)
				{
					return val;
				}
				val = bundle.LoadAsset<Sprite>(text.ToLowerInvariant());
				if ((Object)(object)val != (Object)null)
				{
					return val;
				}
			}
		}
		return null;
	}

	private static string[] BuildIconFallbacks(string prefabName)
	{
		if (prefabName.StartsWith("Poison_Crystal", StringComparison.Ordinal))
		{
			return new string[3] { "Poison_Crystal", "Poison_Crystal_Small", "Poison_Crystal_Large" };
		}
		if (prefabName.StartsWith("Frost_Crystal", StringComparison.Ordinal))
		{
			return new string[3] { "Frost_Crystal", "Frost_Crystal_Small", "Frost_Crystal_Large" };
		}
		if (prefabName.StartsWith("Fire_Crystal", StringComparison.Ordinal))
		{
			return new string[3] { "Fire_Crystal", "Fire_Crystal_Small", "Fire_Crystal_Large" };
		}
		if (prefabName.StartsWith("Lightning_Crystal", StringComparison.Ordinal))
		{
			return new string[3] { "Lightning_Crystal", "Lightning_Crystal_Small", "Lightning_Crystal_Large" };
		}
		if (prefabName.StartsWith("Raven_Crystal", StringComparison.Ordinal))
		{
			return new string[3] { "Raven_Crystal", "Raven_Crystal_Small", "Raven_Crystal_Large" };
		}
		return new string[0];
	}

	private static RelicRegistration CreateElementCrystal(string prefabName, string displayName, string essenceName, int amount)
	{
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Expected O, but got Unknown
		return new RelicRegistration(prefabName, displayName, (RequirementConfig[])(object)new RequirementConfig[1]
		{
			new RequirementConfig(essenceName, amount, 0, true)
		}, "Can be planted with the cultivator.", "Cultivator");
	}

	private static RelicRegistration CreateRavenCrystal(string prefabName, string displayName, int poisonAmount, int frostAmount, int fireAmount, int lightningAmount)
	{
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_0019: Expected O, but got Unknown
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		//IL_0029: Expected O, but got Unknown
		//IL_0034: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: Expected O, but got Unknown
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: Expected O, but got Unknown
		return new RelicRegistration(prefabName, displayName, (RequirementConfig[])(object)new RequirementConfig[4]
		{
			new RequirementConfig("Essence_Poison", poisonAmount, 0, true),
			new RequirementConfig("Essence_Frost", frostAmount, 0, true),
			new RequirementConfig("Essence_Fire", fireAmount, 0, true),
			new RequirementConfig("Essence_Lightning", lightningAmount, 0, true)
		}, "Can be planted with the cultivator.", "Cultivator");
	}
}