Untitled left D:\ValheimDev\Dumps\Latest\assembly_valheim\Vine.cs
.  using System;
  using System.Collections.Generic;
  using UnityEngine;
   
  public class Vine : MonoBehaviour
  {
      private void Awake()
      {
          this.m_nview = base.GetComponent<ZNetView>();
          this.m_pickable = base.GetComponent<Pickable>();
          Pickable pickable = this.m_pickable;
          pickable.m_spawnCheck = (Pickable.SpawnCheck)Delegate.Combine(pickable.m_spawnCheck, new Pickable.SpawnCheck(this.CanSpawnPickable));
          this.GetRandom();
          Vine.s_allVines.Add(this);
          if (Vine.s_pieceMask == 0)
          {
              Vine.s_pieceMask = LayerMask.GetMask(new string[] { "Default", "static_solid", "Default_small", "piece" });
          }
          if (Vine.s_solidMask == 0)
          {
              Vine.s_solidMask = LayerMask.GetMask(new string[]
              {
                  "Default", "static_solid", "Default_small", "piece", "piece_nonsolid", "terrain", "character", "character_net", "character_ghost", "hitbox",
                  "character_noenv", "vehicle" 
              });
          }
          base.InvokeRepeating("CheckSupport", (float)(10 + UnityEngine.Random.Range(0, 7)), 7f);
          base.InvokeRepeating("UpdateGrow", (float)UnityEngine.Random.Range(5, 10 + this.m_growCheckTime), (float)this.m_growCheckTime);
          this.IsDoneGrowing = this.IsDone();
          if (this.m_nview.IsOwner())
          {
              this.m_plantTime = this.m_nview.GetZDO().GetLong(ZDOVars.s_plantTime, 0L);
              if (this.m_plantTime == 0L)
              {
                  long ticks = ZNet.instance.GetTime().Ticks;
                  this.m_nview.GetZDO().Set(ZDOVars.s_plantTime, this.m_plantTime = ticks);
              }
              this.m_vineType = (Vine.VineType)this.m_nview.GetZDO().GetInt(ZDOVars.s_type, 0);
          }
          this.UpdateType();
          this.CheckBerryBlocker();
          string text;
          int num;
          if (Terminal.m_testList.TryGetValue("quickvine", out text) && int.TryParse(text, out num))
          {
              this.m_initialGrowItterations = num;
          }
      }
   
      private void GetRandom()
      {
          if (this.m_rnd == null)
          {
              this.m_rnd = new System.Random((this.m_forceSeed != 0) ? (this.m_forceSeed + this.GetOriginOffset().GetHashCode()) : UnityEngine.Random.Range(int.MinValue, int.MaxValue));
          }
      }
   
      public void Update()
      {
          if (this.m_initialGrowItterations > 0 && this.m_nview && this.m_nview.IsOwner())
          {
              for (int i = 0; i < Mathf.Min(this.m_initialGrowItterations, 25); i++)
              {
                  if (this.UpdateGrow())
                  {
                      this.m_initialGrowItterations--;
                      break;
                  }
                  this.m_initialGrowItterations--;
              }
          }
          bool flag = this.m_pickable.CanBePicked();
          if (flag != this.m_lastPickable)
          {
              this.BerryBlockNeighbours();
              this.m_lastPickable = flag;
          }
      }
   
      public bool UpdateGrow()
      {
          if (!this.m_nview || !this.m_nview.IsOwner())
          {
              return false;
          }
          if (!this.m_dupeCheck)
          {
              this.m_dupeCheck = true;
              foreach (Vine vine in Vine.s_allVines)
              {
                  if (vine != this && vine && Vector3.Distance(vine.transform.position, base.transform.position) < 0.01f)
                  {
                      ZNetScene.instance.Destroy(base.gameObject);
                      return false;
                  }
              }
          }
          if ((this.IsDoneGrowing || this.IsDone()) && this.m_initialGrowItterations > 0)
          {
              this.m_initialGrowItterations = 0;
          }
          if (this.m_initialGrowItterations <= 0)
          {
              float num = (float)(ZNet.instance ? ZNet.instance.GetTime().Ticks : 0L);
              long num2;
              if (this.m_nview)
              {
                  ZDO zdo = this.m_nview.GetZDO();
                  if (zdo != null)
                  {
                      long @long = zdo.GetLong(ZDOVars.s_growStart, 0L);
                      num2 = @long;
                      goto IL_12C;
                  }
              }
              num2 = 0L;
              IL_12C:
              long num3 = num2;
              int num4 = (int)((float)(((long)num - ((this.m_plantTime > num3) ? this.m_plantTime : num3)) / 10000000L) / (this.m_growTime + this.m_growTimePerBranch * (float)this.GetBranches()));
              if (num4 < 1)
              {
                  return false;
              }
              if (num4 >= 2 && num4 > this.m_initialGrowItterations)
              {
                  this.m_initialGrowItterations = num4 - 1;
                  if (Terminal.m_showTests && Terminal.m_testList.ContainsKey("vine"))
                  {
                      Terminal.Log(string.Format("Vine is queuing {0} itterations to catch up!", this.m_initialGrowItterations));
                  }
              }
          }
          if (this.m_nview && this.m_nview.IsOwner() && this.m_nview.IsValid())
          {
              this.m_nview.GetZDO().Set(ZDOVars.s_growStart, ZNet.instance.GetTime().Ticks);
          }
          this.m_originOffset = this.GetOriginOffset();
          int num5 = 0;
          bool flag = this.m_rnd.NextDouble() < (double)this.m_maxGrowEdgeIgnoreChance;
          if (this.m_growSides)
          {
              float num6 = this.m_maxGrowWidth + this.m_originOffset.y * this.m_extraGrowWidthPerHeight;
              if (flag || this.m_originOffset.z + 1f <= num6)
              {
                  num5 += this.CheckGrowChance(new Vector3(0f, 0f, 1f), Vine.VineType.Left, Vine.VineState.ClosedLeft, Vine.VineState.BranchLeft, Vine.VineState.BranchRight);
              }
              else
              {
                  this.m_vineState |= Vine.VineState.ClosedLeft;
              }
              if (flag || Mathf.Abs(this.m_originOffset.z) + 1f <= num6)
              {
                  num5 += this.CheckGrowChance(new Vector3(0f, 0f, -1f), Vine.VineType.Right, Vine.VineState.ClosedRight, Vine.VineState.BranchRight, Vine.VineState.BranchLeft);
              }
              else
              {
                  this.m_vineState |= Vine.VineState.ClosedRight;
              }
          }
          if (this.m_growUp)
          {
              if (flag || this.m_originOffset.y + 1f <= this.m_maxGrowUp)
              {
                  num5 += this.CheckGrowChance(new Vector3(0f, 1f, 0f), Vine.VineType.Top, Vine.VineState.ClosedTop, Vine.VineState.BranchTop, Vine.VineState.BranchBottom);
              }
              else
              {
                  this.m_vineState |= Vine.VineState.ClosedTop;
              }
          }
          if (this.m_growDown)
          {
              if (flag || this.m_originOffset.y - 1f >= this.m_maxGrowDown)
              {
                  num5 += this.CheckGrowChance(new Vector3(0f, -1f, 0f), Vine.VineType.Bottom, Vine.VineState.ClosedBottom, Vine.VineState.BranchBottom, Vine.VineState.BranchTop);
              }
              else
              {
                  this.m_vineState |= Vine.VineState.ClosedBottom;
              }
          }
          this.IsDoneGrowing = this.IsDone();
          return num5 > 0;
      }
   
      private int CheckGrowChance(Vector3 offset, Vine.VineType type, Vine.VineState closed, Vine.VineState branch, Vine.VineState branchFrom)
      {
          if (this.m_rnd.NextDouble() < (double)(this.m_growCheckChance + this.m_growCheckChancePerBranch * (float)this.GetBranches()))
          {
              return this.CheckGrow(offset, type, closed, branch, branchFrom);
          }
          return 0;
      }
   
      private int CheckGrow(Vector3 offset, Vine.VineType type, Vine.VineState closed, Vine.VineState branch, Vine.VineState branchFrom)
      {
          if (this.m_vineState.HasFlag(branch))
          {
              return 0;
          }
          if (this.m_vineState.HasFlag(closed) && this.m_rnd.NextDouble() > 0.4000000059604645)
          {
              return 0;
          }
          if (this.m_rnd.NextDouble() < (double)Mathf.Min(this.m_maxCloseEndChance, this.m_closeEndChance + this.m_closeEndChancePerBranch * (float)this.GetBranches() + this.m_closeEndChancePerHeight * this.GetOriginOffset().y))
          {
              if (this.GetBranches() > 1)
              {
                  this.m_vineState |= closed;
              }
              return 0;
          }
          Vector3 vector = offset;
          if (this.m_randomOffset != 0f)
          {
              if (type - Vine.VineType.Left > 1)
              {
                  if (type - Vine.VineType.Top <= 1)
                  {
                      offset.z += UnityEngine.Random.Range(-this.m_randomOffset, this.m_randomOffset);
                  }
              }
              else
              {
                  offset.y += UnityEngine.Random.Range(-this.m_randomOffset, this.m_randomOffset);
              }
          }
          this.m_sensorBlockCollider.transform.localPosition = Vector3.zero;
          this.m_sensorBlockCollider.transform.Translate(offset * this.m_size + this.m_sensorBlockCollider.center, base.transform);
          int num = Physics.OverlapBoxNonAlloc(this.m_sensorBlockCollider.transform.position, this.m_sensorBlockCollider.size / 2f, Vine.s_colliders, this.m_sensorBlockCollider.transform.rotation, Vine.s_solidMask);
          int i = 0;
          while (i < num)
          {
              Vine componentInParent = Vine.s_colliders[i].GetComponentInParent<Vine>();
              if (!(componentInParent == this))
              {
                  if (componentInParent != null)
                  {
                      if (Terminal.m_showTests && Terminal.m_testList.ContainsKey("vine"))
                      {
                          Terminal.Log("Blocked by vine, count it as a branch (green box)");
                      }
                      this.m_vineState |= branch;
                      this.UpdateBranches();
                      return 0;
                  }
                  if (Terminal.m_showTests && Terminal.m_testList.ContainsKey("vine"))
                  {
                      Terminal.Log("Blocked by piece (red box)");
                  }
                  this.m_vineState |= closed;
                  this.UpdateBranches();
                  return 0;
              }
              else
              {
                  i++;
              }
          }
          this.m_sensorGrow.transform.localPosition = Vector3.zero;
          this.m_sensorGrow.transform.Translate(offset * this.m_size + this.m_sensorGrow.center, base.transform);
          int num2 = 0;
          foreach (BoxCollider boxCollider in this.m_sensorGrowColliders)
          {
              num = Physics.OverlapBoxNonAlloc(this.m_sensorGrow.transform.position, boxCollider.size / 2f, Vine.s_colliders, this.m_sensorGrow.transform.rotation, Vine.s_pieceMask);
              if (num > 0)
              {
                  num2++;
              }
          }
          if ((float)num2 >= (float)this.m_sensorGrowColliders.Count * this.m_growCollidersMinimum && this.m_rnd.NextDouble() < (double)this.m_growChance)
          {
              this.Grow(offset, vector, type, branch, branchFrom);
              return 1;
          }
          return 0;
      }
   
      private void CheckSupport()
      {
          if (!this.IsSupported())
          {
              Destructible component = base.GetComponent<Destructible>();
              if (component != null)
              {
                  component.m_destroyedEffect.Create(base.transform.position, base.transform.rotation, null, 1f, -1);
              }
              else
              {
                  WearNTear component2 = base.GetComponent<WearNTear>();
                  if (component2 != null)
                  {
                      component2.m_destroyedEffect.Create(base.transform.position, base.transform.rotation, null, 1f, -1);
                  }
              }
              ZNetScene.instance.Destroy(base.gameObject);
          }
      }
   
      private bool IsSupported()
      {
          return Physics.OverlapBoxNonAlloc(base.transform.TransformPoint(this.m_supportCollider.center), this.m_supportCollider.size / 2f, Vine.s_colliders, this.m_supportCollider.transform.rotation, Vine.s_pieceMask) > 0;
      }
   
      private int GetBranches()
      {
          return Mathf.Max(0, this.m_branches - 1);
      }
   
      private void Grow(Vector3 offset, Vector3 originOffset, Vine.VineType type, Vine.VineState branch, Vine.VineState growingFrom)
      {
          if (this.m_vineType != Vine.VineType.Full)
          {
              this.SetType(Vine.VineType.Full);
          }
          Vine component = UnityEngine.Object.Instantiate<GameObject>(this.m_vinePrefab, base.transform.position, base.transform.rotation).GetComponent<Vine>();
          component.transform.Translate(offset * this.m_size, Space.Self);
          component.SetType(type);
          component.name = "VineAsh";
          component.m_vineState |= growingFrom;
          component.m_initialGrowItterations = this.m_initialGrowItterations - 1;
          component.m_pickable.m_respawnTimeInitMin += (float)this.m_initialGrowItterations;
          component.m_pickable.m_respawnTimeInitMax += (float)this.m_initialGrowItterations;
          this.m_originOffset = this.GetOriginOffset();
          component.SetOriginOffset(this.m_originOffset + originOffset);
          if (this.m_maxScale != 1f || this.m_minScale != 1f)
          {
              float num = this.m_minScale + (float)(this.m_rnd.NextDouble() * (double)(this.m_maxScale - this.m_minScale));
              component.transform.localScale = new Vector3(num, num, num);
          }
          if (component.m_nview && component.m_nview.IsOwner() && component.m_nview.IsValid())
          {
              component.m_nview.GetZDO().Set(ZDOVars.s_plantTime, ZNet.instance.GetTime().Ticks);
          }
      }
   
      private void SetType(Vine.VineType type)
      {
          this.m_vineType = type;
          if (this.m_nview && this.m_nview.IsOwner() && this.m_nview.IsValid())
          {
              this.m_nview.GetZDO().Set(ZDOVars.s_type, (int)type, false);
          }
          this.UpdateType();
      }
   
      public void SetOriginOffset(Vector3 offset)
      {
          this.m_originOffset = offset;
          if (this.m_nview && this.m_nview.IsValid())
          {
              this.m_nview.GetZDO().Set(ZDOVars.s_offset, this.m_originOffset);
          }
      }
   
      public Vector3 GetOriginOffset()
      {
          if (this.m_originOffset == Vector3.zero && this.m_nview && this.m_nview.IsValid())
          {
              this.m_originOffset = this.m_nview.GetZDO().GetVec3(ZDOVars.s_offset, Vector3.zero);
          }
          return this.m_originOffset;
      }
   
      private void UpdateType()
      {
          this.m_vineFull.SetActive(this.m_vineType == Vine.VineType.Full);
          this.m_vineLeft.SetActive(this.m_vineType == Vine.VineType.Left);
          this.m_vineRight.SetActive(this.m_vineType == Vine.VineType.Right);
          this.m_vineTop.SetActive(this.m_vineType == Vine.VineType.Top);
          this.m_vineBottom.SetActive(this.m_vineType == Vine.VineType.Bottom);
      }
   
      private void UpdateBranches()
      {
          this.m_branches = 0;
          if (this.m_vineState.HasFlag(Vine.VineState.BranchLeft))
          {
              this.m_branches++;
          }
          if (this.m_vineState.HasFlag(Vine.VineState.BranchRight))
          {
              this.m_branches++;
          }
          if (this.m_vineState.HasFlag(Vine.VineState.BranchTop))
          {
              this.m_branches++;
          }
          if (this.m_vineState.HasFlag(Vine.VineState.BranchBottom))
          {
              this.m_branches++;
          }
      }
   
      private void BerryBlockNeighbours()
      {
          if (!this.m_nview || !this.m_nview.IsOwner())
          {
              return;
          }
          if (Terminal.m_showTests && Terminal.m_testList.ContainsKey("vine"))
          {
              Terminal.Log("Vine pickable changed, blocking neighbors");
          }
          int num = Physics.OverlapBoxNonAlloc(base.transform.TransformPoint(this.m_berryBlocker.center), this.m_berryBlocker.size / 2f, Vine.s_colliders, this.m_berryBlocker.transform.rotation, Vine.s_solidMask);
          Vine.s_vines.Clear();
          for (int i = 0; i < num; i++)
          {
              Vine componentInParent = Vine.s_colliders[i].GetComponentInParent<Vine>();
              if (componentInParent != null)
              {
                  Vine.s_vines.Add(componentInParent);
              }
          }
          foreach (Vine vine in Vine.s_vines)
          {
              vine.CheckBerryBlocker();
          }
      }
   
      private bool CanSpawnPickable(Pickable p)
      {
          return this.CheckBerryBlocker();
      }
   
      private bool CheckBerryBlocker()
      {
          if (!this.m_nview || !this.m_nview.IsOwner())
          {
              return true;
          }
          if (this.m_pickable.CanBePicked())
          {
              return true;
          }
          int num = Physics.OverlapBoxNonAlloc(base.transform.TransformPoint(this.m_berryBlocker.center), this.m_berryBlocker.size / 2f, Vine.s_colliders, this.m_berryBlocker.transform.rotation, Vine.s_solidMask);
          int num2 = 0;
          for (int i = 0; i < num; i++)
          {
              Vine componentInParent = Vine.s_colliders[i].GetComponentInParent<Vine>();
              if (componentInParent != null && componentInParent.m_pickable.CanBePicked())
              {
                  num2++;
              }
          }
          this.UpdateBranches();
          bool flag = num2 < this.m_maxBerriesWithinBlocker && this.GetBranches() > 0;
          if (!flag)
          {
              this.m_pickable.SetPicked(true);
          }
          if (Terminal.m_showTests && Terminal.m_testList.ContainsKey("vine"))
          {
              Terminal.Log(string.Format("Vine checking berry blockers. Berries: {0}, Pickable: {1}", num2, flag));
          }
          return flag;
      }
   
      private bool IsDone()
      {
          return (this.m_vineState.HasFlag(Vine.VineState.ClosedLeft) || this.m_vineState.HasFlag(Vine.VineState.BranchLeft)) && (this.m_vineState.HasFlag(Vine.VineState.ClosedRight) || this.m_vineState.HasFlag(Vine.VineState.BranchRight)) && (this.m_vineState.HasFlag(Vine.VineState.ClosedTop) || this.m_vineState.HasFlag(Vine.VineState.BranchTop));
      }
   
      private void OnDestroy()
      {
          Vine.s_allVines.Remove(this);
      }
   
      public bool IsDoneGrowing { get; private set; }
   
      private static int s_pieceMask;
   
      private static int s_solidMask;
   
      [Header("Grow Settings")]
      [global::Tooltip("Chance that a grow check is run on each open branch, which can result in a chance to grow or chance to close.")]
      [Range(0f, 1f)]
      public float m_growCheckChance = 0.3f;
   
      [global::Tooltip("Grow check decreases by this amount for each near branch.")]
      [Range(-1f, 0f)]
      public float m_growCheckChancePerBranch = -0.75f;
   
      [global::Tooltip("Chance that a possible branch will actually grow")]
      [Range(0f, 1f)]
      public float m_growChance = 0.5f;
   
      [global::Tooltip("At what interval the GrowCheck function will repeat.")]
      public int m_growCheckTime = 5;
   
      [global::Tooltip("Seconds it will take between each attempt to grow.")]
      public float m_growTime = 3f;
   
      [global::Tooltip("Extra seconds it will take between each attempt to grow for each branch connected to it.")]
      public float m_growTimePerBranch = 2f;
   
      [global::Tooltip("Chance that a branch will close after during a grow check.")]
      [Range(0f, 1f)]
      public float m_closeEndChance;
   
      [global::Tooltip("Close chance increases by this amount for each near branch.")]
      [Range(0f, 1f)]
      public float m_closeEndChancePerBranch = 0.1f;
   
      [global::Tooltip("Close chance increases by this amount for each height.")]
      [Range(0f, 1f)]
      public float m_closeEndChancePerHeight = 0.2f;
   
      [global::Tooltip("Close chance will never go above this. (Also will never be closed unless there is atleast one grown branch.")]
      [Range(0f, 1f)]
      public float m_maxCloseEndChance = 0.9f;
   
      public float m_maxGrowUp = 1000f;
   
      public float m_maxGrowDown = -2f;
   
      [global::Tooltip("Grow width limitation")]
      public float m_maxGrowWidth = 3f;
   
      [global::Tooltip("Extra grow width limitation per height")]
      public float m_extraGrowWidthPerHeight = 0.5f;
   
      [global::Tooltip("Chance to ignore width limitaion.")]
      [Range(0f, 1f)]
      public float m_maxGrowEdgeIgnoreChance = 0.2f;
   
      [global::Tooltip("Vine will grow this many itterations upon placement. Used for locations for instant growing. Test with console 'test quickvine 300'")]
      public int m_initialGrowItterations;
   
      public int m_forceSeed;
   
      public float m_size = 1.5f;
   
      [global::Tooltip("At least this much % of the colliders must find support to be able to grow.")]
      [Range(0f, 1f)]
      public float m_growCollidersMinimum = 0.75f;
   
      public bool m_growSides = true;
   
      public bool m_growUp = true;
   
      public bool m_growDown;
   
      public float m_minScale = 1f;
   
      public float m_maxScale = 1f;
   
      public float m_randomOffset = 0.1f;
   
      [Header("Berries")]
      public int m_maxBerriesWithinBlocker = 2;
   
      public BoxCollider m_berryBlocker;
   
      [Header("Prefabs")]
      public GameObject m_vinePrefab;
   
      public GameObject m_vineFull;
   
      public GameObject m_vineTop;
   
      public GameObject m_vineBottom;
   
      public GameObject m_vineLeft;
   
      public GameObject m_vineRight;
   
      public BoxCollider m_sensorGrow;
   
      public BoxCollider m_supportCollider;
   
      public List<BoxCollider> m_sensorGrowColliders;
   
      public GameObject m_sensorBlock;
   
      public BoxCollider m_sensorBlockCollider;
   
      public BoxCollider m_placementCollider;
   
      [Header("Testing")]
      public int m_testItterations = 10;
   
      [NonSerialized]
      public Vine.VineState m_vineState;
   
      private Pickable m_pickable;
   
      private bool m_lastPickable;
   
      private long m_plantTime;
   
      private long m_lastGrow;
   
      private ZNetView m_nview;
   
      private Vine.VineType m_vineType;
   
      private int m_branches;
   
      private Vector3 m_originOffset;
   
      private System.Random m_rnd;
   
      private bool m_dupeCheck;
   
      private static Collider[] s_colliders = new Collider[20];
   
      private static List<Vine> s_vines = new List<Vine>();
   
      private static List<Vine> s_allVines = new List<Vine>();
   
      [Flags]
      public enum VineState
      {
          None = 0,
          ClosedLeft = 1,
          ClosedRight = 2,
          ClosedTop = 4,
          ClosedBottom = 8,
          BranchLeft = 16,
          BranchRight = 32,
          BranchTop = 64,
          BranchBottom = 128
      }
   
      private enum VineType
      {
          Full,
          Left,
          Right,
          Top,
          Bottom
      }
  }