Decompiled source of OdinsTree v0.1.0

OdinsTree.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("assembly_utils")]
[assembly: IgnoresAccessChecksTo("assembly_valheim")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("OdinsTree")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+e10c00b668839f1d4e77b711134e868d3fb13289")]
[assembly: AssemblyProduct("OdinsTree")]
[assembly: AssemblyTitle("OdinsTree")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[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;
		}
	}
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}
namespace OdinsTree
{
	[BepInPlugin("rauschekuh.odinstree", "Odin's Tree", "0.1.0")]
	public class OdinsTreePlugin : BaseUnityPlugin
	{
		[HarmonyPatch(typeof(TreeBase), "Awake")]
		private static class RememberTree
		{
			private static void Postfix(TreeBase __instance)
			{
				trees.Add(__instance);
			}
		}

		private class BlessedLook : MonoBehaviour
		{
			private const float GlowSeconds = 6f;

			private GameObject glow;

			public void Bless()
			{
				//IL_000c: Unknown result type (might be due to invalid IL or missing references)
				Lift();
				Strike(((Component)this).transform.position);
				((MonoBehaviour)this).Invoke("Burst", 0.7f);
			}

			public void Lift()
			{
				((MonoBehaviour)this).CancelInvoke("Burst");
				if ((Object)(object)glow != (Object)null)
				{
					Object.Destroy((Object)(object)glow);
				}
			}

			private static void Strike(Vector3 pos)
			{
				//IL_002f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0035: Expected O, but got Unknown
				//IL_003b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0055: Unknown result type (might be due to invalid IL or missing references)
				//IL_005b: Expected O, but got Unknown
				GameObject val = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab("lightningAOE") : null);
				if ((Object)(object)val == (Object)null)
				{
					return;
				}
				GameObject val2 = new GameObject("OdinsTree_lightning");
				val2.transform.position = pos;
				foreach (Transform item in val.transform)
				{
					Transform val3 = item;
					if ((Object)(object)((Component)val3).GetComponent<Aoe>() == (Object)null)
					{
						Object.Instantiate<GameObject>(((Component)val3).gameObject, val2.transform, false);
					}
				}
				Object.Destroy((Object)(object)val2, 10f);
			}

			private void Burst()
			{
				//IL_003a: Unknown result type (might be due to invalid IL or missing references)
				//IL_003f: Unknown result type (might be due to invalid IL or missing references)
				//IL_004d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0053: Unknown result type (might be due to invalid IL or missing references)
				StatusEffect val = (((Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.GetStatusEffect(StringExtensionMethods.GetStableHashCode("GP_Eikthyr")) : null);
				if ((Object)(object)val != (Object)null)
				{
					val.m_startEffects.Create(((Component)this).transform.position, Quaternion.identity, (Transform)null, 1f, -1, default(ZDOID));
				}
				glow = Glow(((Component)this).transform);
				if ((Object)(object)glow != (Object)null)
				{
					Object.Destroy((Object)(object)glow, 6f);
				}
			}

			private static GameObject Glow(Transform tree)
			{
				//IL_008d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0092: Unknown result type (might be due to invalid IL or missing references)
				//IL_0099: 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_00ba: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
				//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
				GameObject val = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab("BossStone_Eikthyr") : null);
				BossStone val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<BossStone>() : null);
				if ((Object)(object)val2 == (Object)null || (Object)(object)val2.m_activeEffect == (Object)null)
				{
					return null;
				}
				GameObject val3 = Object.Instantiate<GameObject>(val2.m_activeEffect, tree, false);
				GuidePoint[] componentsInChildren = val3.GetComponentsInChildren<GuidePoint>(true);
				foreach (GuidePoint obj in componentsInChildren)
				{
					((Behaviour)obj).enabled = false;
					Object.Destroy((Object)(object)((Component)obj).gameObject);
				}
				Vector3 lossyScale = tree.lossyScale;
				val3.transform.localPosition = Vector3.zero;
				val3.transform.localScale = new Vector3(1f / lossyScale.x, 1f / lossyScale.y, 1f / lossyScale.z);
				val3.SetActive(true);
				return val3;
			}
		}

		[HarmonyPatch(typeof(Player), "Repair")]
		private static class BlessOnRepair
		{
			private static bool Prefix(Player __instance, ItemData toolItem, Piece repairPiece)
			{
				//IL_0030: 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_00ab: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
				TreeBase val = AimedTree(__instance);
				if ((Object)(object)val == (Object)null)
				{
					return true;
				}
				ZNetView nview = val.m_nview;
				if ((Object)(object)nview == (Object)null || !nview.IsValid() || !PrivateArea.CheckAccess(((Component)val).transform.position, 0f, true, false))
				{
					return false;
				}
				bool flag = IsBlessed(val);
				nview.ClaimOwnership();
				nview.GetZDO().Set(ZDOVars.s_health, flag ? val.m_health : 1E+12f);
				BlessedLook blessedLook = ((Component)val).GetComponent<BlessedLook>();
				if (flag)
				{
					if ((Object)(object)blessedLook != (Object)null)
					{
						blessedLook.Lift();
					}
					if ((Object)(object)repairPiece != (Object)null)
					{
						repairPiece.m_placeEffect.Create(((Component)val).transform.position, ((Component)val).transform.rotation, (Transform)null, 1f, -1, ((Character)__instance).GetZDOID());
					}
				}
				else
				{
					if ((Object)(object)blessedLook == (Object)null)
					{
						blessedLook = ((Component)val).gameObject.AddComponent<BlessedLook>();
					}
					blessedLook.Bless();
				}
				((Character)__instance).Message((MessageType)1, flag ? "The blessing is lifted" : "This tree is blessed by Odin", 0, (Sprite)null, false);
				SwingHammer(__instance, toolItem);
				return false;
			}
		}

		[HarmonyPatch(typeof(TreeBase))]
		private static class UnhittableWhenBlessed
		{
			[HarmonyPrefix]
			[HarmonyPatch("Damage")]
			private static bool Damage(TreeBase __instance)
			{
				return !IsBlessed(__instance);
			}

			[HarmonyPrefix]
			[HarmonyPatch("RPC_Damage")]
			private static bool RPC_Damage(TreeBase __instance)
			{
				return !IsBlessed(__instance);
			}
		}

		[HarmonyPatch(typeof(Hud), "UpdateCrosshair")]
		private static class TreeHoverText
		{
			private static void Postfix(Hud __instance, Player player)
			{
				//IL_004c: Unknown result type (might be due to invalid IL or missing references)
				string text = HoverText(player, AimedObject(player));
				if (text.Length != 0)
				{
					Traverse.Create((object)__instance).Field("m_hoverName").Property("text", (object[])null)
						.SetValue((object)text);
					if ((Object)(object)__instance.m_crosshair != (Object)null)
					{
						((Graphic)__instance.m_crosshair).color = Color.yellow;
					}
				}
			}
		}

		[HarmonyPatch(typeof(Player), "UpdatePlacementGhost")]
		private static class GuardGhost
		{
			private static void Postfix(Player __instance)
			{
				//IL_0019: Unknown result type (might be due to invalid IL or missing references)
				//IL_0037: Unknown result type (might be due to invalid IL or missing references)
				//IL_004c: Unknown result type (might be due to invalid IL or missing references)
				GameObject placementGhost = __instance.m_placementGhost;
				if (!((Object)(object)placementGhost == (Object)null) && placementGhost.activeSelf && (int)__instance.m_placementStatus == 0)
				{
					TerrainOp componentInChildren = placementGhost.GetComponentInChildren<TerrainOp>();
					if (!((Object)(object)componentInChildren == (Object)null) && NearBlessedTree(placementGhost.transform.position, componentInChildren.GetRadius()))
					{
						__instance.m_placementStatus = (PlacementStatus)1;
						__instance.SetPlacementGhostValid(false);
					}
				}
			}
		}

		[HarmonyPatch(typeof(TerrainOp), "Awake")]
		private static class GuardTerrainOp
		{
			private static bool Prefix(TerrainOp __instance)
			{
				//IL_000d: Unknown result type (might be due to invalid IL or missing references)
				if (TerrainOp.m_forceDisableTerrainOps || !NearBlessedTree(((Component)__instance).transform.position, __instance.GetRadius()))
				{
					return true;
				}
				Player localPlayer = Player.m_localPlayer;
				if (localPlayer != null)
				{
					((Character)localPlayer).Message((MessageType)2, "Odin's tree guards this ground", 0, (Sprite)null, false);
				}
				Object.Destroy((Object)(object)((Component)__instance).gameObject);
				return false;
			}
		}

		[HarmonyPatch(typeof(TerrainComp), "RPC_ApplyOperation")]
		private static class GuardTerrainOwner
		{
			private static bool Prefix(TerrainComp __instance, long sender, ZPackage pkg)
			{
				//IL_0036: Unknown result type (might be due to invalid IL or missing references)
				//IL_003b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0045: Unknown result type (might be due to invalid IL or missing references)
				//IL_005c: Unknown result type (might be due to invalid IL or missing references)
				if (TerrainGuardRadius.Value <= 0f || (Object)(object)__instance.m_nview == (Object)null || !__instance.m_nview.IsOwner())
				{
					return true;
				}
				int pos = pkg.GetPos();
				Vector3 point = pkg.ReadVector3();
				if (pkg.ReadBool())
				{
					pkg.ReadVector3();
				}
				Settings val = Settings.Deserialize(pkg);
				pkg.SetPos(pos);
				if (val == null || !NearBlessedTreeZDO(point, val.GetRadius()))
				{
					return true;
				}
				if (ZRoutedRpc.instance != null)
				{
					ZRoutedRpc.instance.InvokeRoutedRPC(sender, "ShowMessage", new object[2] { 2, "Odin's tree guards this ground" });
				}
				return false;
			}
		}

		private static class Warden
		{
			[HarmonyPatch(typeof(ZDOMan), "ReleaseNearbyZDOS")]
			private static class TakeCompilers
			{
				private static void Postfix(ZDOMan __instance)
				{
					//IL_0048: 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_0088: Unknown result type (might be due to invalid IL or missing references)
					//IL_009f: Unknown result type (might be due to invalid IL or missing references)
					//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
					//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
					//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
					//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
					if (TerrainGuardRadius.Value <= 0f || (Object)(object)ZoneSystem.instance == (Object)null)
					{
						return;
					}
					zones.Clear();
					foreach (ZDO tempNearObject in __instance.m_tempNearObjects)
					{
						if (IsBlessedTree(tempNearObject))
						{
							AddZonesInReach(tempNearObject.GetPosition());
						}
					}
					foreach (Vector2s zone in zones)
					{
						bool flag = ZoneSystem.instance.PokeLocalZone(zone);
						sector.Clear();
						ZDOMan.instance.FindSectorObjects(zone, new SimulationDistance(0, 0, true), sector, (List<ZDO>)null);
						ZDO val = sector.Find((ZDO z) => z.GetPrefab() == CompilerPrefab);
						if (val == null && !flag && ZoneSystem.instance.IsZoneLoaded(zone))
						{
							Heightmap val2 = Heightmap.FindHeightmap(ZoneSystem.GetZonePos(zone));
							TerrainComp val3 = (((Object)(object)val2 != (Object)null) ? val2.GetAndCreateTerrainCompiler() : null);
							val = (((Object)(object)val3 != (Object)null && (Object)(object)val3.m_nview != (Object)null) ? val3.m_nview.GetZDO() : null);
						}
						if (val != null)
						{
							Hold(val);
						}
					}
				}
			}

			[HarmonyPatch(typeof(ZDOMan), "IsInPeerActiveArea")]
			private static class KeepOwnership
			{
				private static void Postfix(Vector3 point, long uid, ref bool __result)
				{
					//IL_002d: Unknown result type (might be due to invalid IL or missing references)
					//IL_0032: Unknown result type (might be due to invalid IL or missing references)
					//IL_0038: 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)
					if (__result || held.Count == 0 || uid != ZDOMan.GetSessionID())
					{
						return;
					}
					foreach (ZDOID key in held.Keys)
					{
						ZDO zDO = ZDOMan.instance.GetZDO(key);
						if (zDO != null && zDO.GetPosition() == point)
						{
							__result = true;
							break;
						}
					}
				}
			}

			[HarmonyPatch(typeof(ZNetScene), "CreateObjects")]
			private static class KeepCompilers
			{
				private static void Prefix(List<ZDO> currentNearObjects)
				{
					//IL_0033: Unknown result type (might be due to invalid IL or missing references)
					//IL_005c: Unknown result type (might be due to invalid IL or missing references)
					//IL_006e: Unknown result type (might be due to invalid IL or missing references)
					//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
					//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
					//IL_00be: Unknown result type (might be due to invalid IL or missing references)
					if (held.Count == 0)
					{
						return;
					}
					stale.Clear();
					foreach (KeyValuePair<ZDOID, float> item in held)
					{
						ZDO zDO = ZDOMan.instance.GetZDO(item.Key);
						if (zDO == null || Time.time - item.Value > 10f)
						{
							stale.Add(item.Key);
						}
						else if (ZoneSystem.instance.IsZoneLoaded(zDO.GetSector()) && !currentNearObjects.Contains(zDO))
						{
							currentNearObjects.Add(zDO);
						}
					}
					foreach (ZDOID item2 in stale)
					{
						held.Remove(item2);
					}
				}
			}

			private const float Reach = 16f;

			private const float Forget = 10f;

			private static readonly int CompilerPrefab = StringExtensionMethods.GetStableHashCode("_TerrainCompiler");

			private static readonly Dictionary<ZDOID, float> held = new Dictionary<ZDOID, float>();

			private static readonly HashSet<Vector2s> zones = new HashSet<Vector2s>();

			private static readonly List<ZDO> sector = new List<ZDO>();

			private static readonly List<ZDOID> stale = new List<ZDOID>();

			private static void AddZonesInReach(Vector3 pos)
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_0028: Unknown result type (might be due to invalid IL or missing references)
				//IL_0030: Unknown result type (might be due to invalid IL or missing references)
				//IL_003d: Unknown result type (might be due to invalid IL or missing references)
				//IL_003f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0044: Unknown result type (might be due to invalid IL or missing references)
				//IL_0046: Unknown result type (might be due to invalid IL or missing references)
				//IL_004c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0065: Unknown result type (might be due to invalid IL or missing references)
				//IL_006b: Unknown result type (might be due to invalid IL or missing references)
				//IL_009a: Unknown result type (might be due to invalid IL or missing references)
				Vector2s zone = ZoneSystem.GetZone(pos);
				float num = ZoneSystem.instance.m_zoneSize * 0.5f;
				Vector2s val = default(Vector2s);
				for (int i = -1; i <= 1; i++)
				{
					for (int j = -1; j <= 1; j++)
					{
						((Vector2s)(ref val))..ctor(zone.x + j, zone.y + i);
						Vector3 zonePos = ZoneSystem.GetZonePos(val);
						float num2 = Mathf.Max(Mathf.Abs(pos.x - zonePos.x) - num, 0f);
						float num3 = Mathf.Max(Mathf.Abs(pos.z - zonePos.z) - num, 0f);
						if (num2 * num2 + num3 * num3 < 256f)
						{
							zones.Add(val);
						}
					}
				}
			}

			private static void Hold(ZDO compiler)
			{
				//IL_001c: Unknown result type (might be due to invalid IL or missing references)
				long sessionID = ZDOMan.GetSessionID();
				if (compiler.GetOwner() != sessionID)
				{
					compiler.SetOwner(sessionID);
				}
				held[compiler.m_uid] = Time.time;
			}
		}

		[HarmonyPatch(typeof(Player), "RemovePiece")]
		private static class CycleOnRemove
		{
			private static bool Prefix(Player __instance, ref bool __result)
			{
				//IL_006c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0090: Unknown result type (might be due to invalid IL or missing references)
				//IL_0096: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
				GameObject val = AimedObject(__instance);
				ZNetView val2 = (((Object)(object)val != (Object)null) ? val.GetComponentInParent<ZNetView>() : null);
				GameObject val3 = (((Object)(object)val2 != (Object)null) ? NextKind(((Component)val2).gameObject) : null);
				if ((Object)(object)val3 == (Object)null)
				{
					return true;
				}
				__result = false;
				if (IsBlessed(((Component)val2).GetComponent<TreeBase>()))
				{
					((Character)__instance).Message((MessageType)2, "Blessed by Odin - lift the blessing first", 0, (Sprite)null, false);
					return false;
				}
				if (!val2.IsValid() || !PrivateArea.CheckAccess(((Component)val2).transform.position, 0f, true, false))
				{
					return false;
				}
				Transform transform = ((Component)val2).transform;
				val2.ClaimOwnership();
				ZNetView component = Object.Instantiate<GameObject>(val3, transform.position, transform.rotation).GetComponent<ZNetView>();
				if (component != null)
				{
					component.SetLocalScale(transform.localScale);
				}
				val2.Destroy();
				SwingHammer(__instance, ((Humanoid)__instance).GetRightItem());
				return false;
			}
		}

		[HarmonyPatch(typeof(Player), "SetControls")]
		private static class CountCrouches
		{
			private static void Prefix(Player __instance, bool crouch)
			{
				if (crouch && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer))
				{
					float time = Time.time;
					crouches = ((!(time - lastCrouch <= 1.5f)) ? 1 : (crouches + 1));
					lastCrouch = time;
				}
			}
		}

		public const string GUID = "rauschekuh.odinstree";

		public const string NAME = "Odin's Tree";

		public const string VERSION = "0.1.0";

		private const float BlessedHealth = 1E+12f;

		private const float BlessedThreshold = 100000000f;

		private const float TwerkRadius = 3f;

		private const float MaxCrouchInterval = 1.5f;

		private const int TwerkCrouches = 3;

		private static readonly Color TwerkGreen = new Color(0.4f, 1f, 0.3f);

		internal static ConfigEntry<float> TerrainGuardRadius;

		internal static ConfigEntry<float> TwerkGrowSeconds;

		internal static ConfigEntry<string> Families;

		private static readonly List<TreeBase> trees = new List<TreeBase>();

		private static List<List<string>> families;

		private static int crouches;

		private static float lastCrouch = -999f;

		private static float lastWhyNotGrowing = -999f;

		private static readonly List<Plant> glowing = new List<Plant>();

		private static readonly List<ZDO> nearZDOs = new List<ZDO>();

		private static HashSet<int> treePrefabs;

		private static bool Twerking
		{
			get
			{
				if (crouches >= 3)
				{
					return Time.time - lastCrouch <= 1.5f;
				}
				return false;
			}
		}

		private void Awake()
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Expected O, but got Unknown
			TerrainGuardRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Blessing", "TerrainGuardRadius", 3f, new ConfigDescription("How far from a blessed tree's trunk the ground cannot be dug, raised or levelled, in metres. 0 lets the ground be changed right up to the trunk. On a server this is what players without the mod are held to.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f), Array.Empty<object>()));
			TwerkGrowSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Growth", "TwerkGrowSeconds", 15f, new ConfigDescription("How many seconds of dodging back and forth beside a sapling grow it into a tree. 0 switches twerking off.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 60f), Array.Empty<object>()));
			Families = ((BaseUnityPlugin)this).Config.Bind<string>("Kinds", "Families", "Birch1,Birch2,Birch1_aut,Birch2_aut;Beech_small1,Beech_small2,Beech1;FirTree_small,FirTree,FirTree_big;Pinetree_01,Pinetree_Snow;YggaShoot1,YggaShoot2,YggaShoot3;SwampTree1,SwampTree2", "Which trees the hammer's remove click cycles through, as prefab names: commas between the kinds of one family, semicolons between families. Whatever a sapling can grow into is a family already; unknown names are ignored.");
			Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "rauschekuh.odinstree");
		}

		private static bool IsBlessed(TreeBase tree)
		{
			ZNetView val = (((Object)(object)tree != (Object)null) ? tree.m_nview : null);
			if ((Object)(object)val != (Object)null && val.IsValid())
			{
				return val.GetZDO().GetFloat(ZDOVars.s_health, tree.m_health) >= 100000000f;
			}
			return false;
		}

		private static GameObject AimedObject(Player player)
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)player == (Object)null)
			{
				return null;
			}
			if (!((Character)player).InPlaceMode())
			{
				return ((Humanoid)player).GetHoverObject();
			}
			if ((Object)(object)GameCamera.instance == (Object)null || (Object)(object)((Character)player).m_eye == (Object)null)
			{
				return null;
			}
			Transform transform = ((Component)GameCamera.instance).transform;
			RaycastHit val = default(RaycastHit);
			if (!Physics.Raycast(transform.position, transform.forward, ref val, 50f, player.m_removeRayMask) || Vector3.Distance(((Character)player).m_eye.position, ((RaycastHit)(ref val)).point) >= player.m_maxPlaceDistance)
			{
				return null;
			}
			return ((Component)((RaycastHit)(ref val)).collider).gameObject;
		}

		private static TreeBase AimedTree(Player player)
		{
			GameObject val = AimedObject(player);
			if (!((Object)(object)val != (Object)null))
			{
				return null;
			}
			return val.GetComponentInParent<TreeBase>();
		}

		private static string HoverText(Player player, GameObject aimed)
		{
			if ((Object)(object)aimed == (Object)null)
			{
				return "";
			}
			TreeBase componentInParent = aimed.GetComponentInParent<TreeBase>();
			ZNetView componentInParent2 = aimed.GetComponentInParent<ZNetView>();
			bool flag = IsBlessed(componentInParent);
			string text = (flag ? "Blessed by Odin" : "");
			if (!((Character)player).InPlaceMode())
			{
				return text;
			}
			if ((Object)(object)componentInParent != (Object)null)
			{
				Piece selectedPiece = player.GetSelectedPiece();
				if (selectedPiece != null && selectedPiece.m_repairPiece)
				{
					text += (flag ? "\n[LMB] Lift blessing" : "\n[LMB] Bless");
				}
			}
			if (!flag && (Object)(object)componentInParent2 != (Object)null && (Object)(object)NextKind(((Component)componentInParent2).gameObject) != (Object)null)
			{
				text += "\n[RMB] Next kind";
			}
			return text.TrimStart(new char[1] { '\n' });
		}

		private static bool NearBlessedTree(Vector3 point, float radius)
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			float value = TerrainGuardRadius.Value;
			if (value <= 0f)
			{
				return false;
			}
			for (int num = trees.Count - 1; num >= 0; num--)
			{
				TreeBase val = trees[num];
				if ((Object)(object)val == (Object)null)
				{
					trees.RemoveAt(num);
				}
				else if (IsBlessed(val) && Utils.DistanceXZ(((Component)val).transform.position, point) < value + radius)
				{
					return true;
				}
			}
			return false;
		}

		private static bool NearBlessedTreeZDO(Vector3 point, float radius)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			float value = TerrainGuardRadius.Value;
			if (value <= 0f || ZDOMan.instance == null)
			{
				return false;
			}
			nearZDOs.Clear();
			ZDOMan.instance.FindSectorObjects(ZoneSystem.GetZone(point), new SimulationDistance(1, 0, true), nearZDOs, (List<ZDO>)null);
			foreach (ZDO nearZDO in nearZDOs)
			{
				if (IsBlessedTree(nearZDO) && Utils.DistanceXZ(nearZDO.GetPosition(), point) < value + radius)
				{
					return true;
				}
			}
			return false;
		}

		private static bool IsBlessedTree(ZDO zdo)
		{
			if (treePrefabs == null)
			{
				if ((Object)(object)ZNetScene.instance == (Object)null)
				{
					return false;
				}
				treePrefabs = new HashSet<int>();
				foreach (KeyValuePair<int, GameObject> namedPrefab in ZNetScene.instance.m_namedPrefabs)
				{
					if ((Object)(object)namedPrefab.Value != (Object)null && (Object)(object)namedPrefab.Value.GetComponent<TreeBase>() != (Object)null)
					{
						treePrefabs.Add(namedPrefab.Key);
					}
				}
			}
			if (treePrefabs.Contains(zdo.GetPrefab()))
			{
				return zdo.GetFloat(ZDOVars.s_health, 0f) >= 100000000f;
			}
			return false;
		}

		private static List<List<string>> GetFamilies()
		{
			if (families != null || (Object)(object)ZNetScene.instance == (Object)null)
			{
				return families;
			}
			families = new List<List<string>>();
			foreach (GameObject prefab in ZNetScene.instance.m_prefabs)
			{
				Plant val = (((Object)(object)prefab != (Object)null) ? prefab.GetComponent<Plant>() : null);
				if ((Object)(object)val != (Object)null && val.m_grownPrefabs != null && val.m_grownPrefabs.Length > 1)
				{
					AddFamily(from p in val.m_grownPrefabs
						where (Object)(object)p != (Object)null
						select ((Object)p).name);
				}
			}
			string[] array = (Families.Value ?? "").Split(new char[1] { ';' });
			for (int num = 0; num < array.Length; num++)
			{
				AddFamily(from s in array[num].Split(new char[1] { ',' })
					select s.Trim() into s
					where s.Length > 0
					select s);
			}
			return families;
		}

		private static void AddFamily(IEnumerable<string> names)
		{
			List<string> kinds = names.Distinct().ToList();
			if (kinds.Count < 2)
			{
				return;
			}
			List<string> existing = families.FirstOrDefault((List<string> f) => f.Intersect(kinds).Any());
			if (existing == null)
			{
				families.Add(kinds);
				return;
			}
			existing.AddRange(kinds.Where((string k) => !existing.Contains(k)));
		}

		private static GameObject NextKind(GameObject tree)
		{
			List<List<string>> list = GetFamilies();
			if ((Object)(object)tree == (Object)null || list == null)
			{
				return null;
			}
			string name = Utils.GetPrefabName(tree);
			List<string> list2 = list.FirstOrDefault((List<string> f) => f.Contains(name));
			if (list2 == null)
			{
				return null;
			}
			int num = list2.IndexOf(name);
			for (int num2 = 1; num2 < list2.Count; num2++)
			{
				GameObject prefab = ZNetScene.instance.GetPrefab(list2[(num + num2) % list2.Count]);
				if ((Object)(object)prefab != (Object)null)
				{
					return prefab;
				}
			}
			return null;
		}

		private static void SwingHammer(Player player, ItemData tool)
		{
			player.FaceLookDirection();
			if (tool != null)
			{
				((Character)player).m_zanim.SetTrigger(tool.m_shared.m_attack.m_attackAnimation);
			}
			((Character)player).UseStamina(player.GetBuildStamina());
			player.m_lastToolUseTime = Time.time;
		}

		private void Update()
		{
			//IL_00ba: 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)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			float value = TwerkGrowSeconds.Value;
			if ((Object)(object)localPlayer == (Object)null || (Object)(object)ZNet.instance == (Object)null || value <= 0f || !Twerking)
			{
				if (glowing.Count > 0)
				{
					StopGlowing();
				}
				return;
			}
			float time = Time.time;
			List<Plant> list = new List<Plant>();
			foreach (SlowUpdate allInstace in SlowUpdate.GetAllInstaces())
			{
				Plant val = (Plant)(object)((allInstace is Plant) ? allInstace : null);
				ZNetView val2 = (((Object)(object)val != (Object)null) ? val.m_nview : null);
				if ((Object)(object)val2 == (Object)null || !val2.IsValid() || val.m_grownPrefabs == null || val.m_grownPrefabs.Length == 0 || Utils.DistanceXZ(((Component)val).transform.position, ((Component)localPlayer).transform.position) > 3f)
				{
					continue;
				}
				val.UpdateHealth(val.TimeSincePlanted());
				if ((int)val.GetStatus() != 0)
				{
					if (time - lastWhyNotGrowing > 2f)
					{
						lastWhyNotGrowing = time;
						((Character)localPlayer).Message((MessageType)1, val.GetHoverText(), 0, (Sprite)null, false);
					}
				}
				else
				{
					list.Add(val);
				}
			}
			foreach (Plant item in glowing.ToList())
			{
				if ((Object)(object)item == (Object)null || !list.Contains(item))
				{
					Unglow(item);
				}
			}
			foreach (Plant item2 in list)
			{
				Glow(item2);
				item2.m_nview.ClaimOwnership();
				ZDO zDO = item2.m_nview.GetZDO();
				float growTime = item2.GetGrowTime();
				long num = zDO.GetLong(ZDOVars.s_plantTime, ZNet.instance.GetTime().Ticks);
				long num2 = (long)(growTime * Time.deltaTime / value * 10000000f);
				zDO.Set(ZDOVars.s_plantTime, num - num2);
				item2.m_updateTime = 0f;
				if (item2.TimeSincePlanted() > (double)growTime)
				{
					Unglow(item2);
					item2.Grow();
				}
			}
		}

		private static void Glow(Plant plant)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			if (!glowing.Contains(plant) && !((Object)(object)MaterialMan.instance == (Object)null))
			{
				MaterialMan.instance.SetValue<Color>(((Component)plant).gameObject, ShaderProps._Color, TwerkGreen, true);
				MaterialMan.instance.SetValue<Color>(((Component)plant).gameObject, ShaderProps._EmissionColor, TwerkGreen * 0.4f, false);
				glowing.Add(plant);
			}
		}

		private static void Unglow(Plant plant)
		{
			glowing.Remove(plant);
			if ((Object)(object)plant != (Object)null && (Object)(object)MaterialMan.instance != (Object)null)
			{
				MaterialMan.instance.ResetValue(((Component)plant).gameObject, ShaderProps._Color);
				MaterialMan.instance.ResetValue(((Component)plant).gameObject, ShaderProps._EmissionColor);
			}
		}

		private static void StopGlowing()
		{
			foreach (Plant item in glowing.ToList())
			{
				Unglow(item);
			}
			glowing.Clear();
		}
	}
}