Decompiled source of BaseAssistant v0.1.3

plugins\BaseAssistant.dll

Decompiled 7 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
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 Jotunn;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")]
[assembly: AssemblyCompany("BaseAssistant")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Base Assistant Mod for Valheim")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+f4c8ee754032a6b2544ff8e5e85a0bde6031bd1d")]
[assembly: AssemblyProduct("BaseAssistant")]
[assembly: AssemblyTitle("BaseAssistant")]
[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;
		}
	}
}
namespace BaseAssistant
{
	public class AssistantAI : MonoBehaviour
	{
		private ZNetView _nview;

		private Character _character;

		private MonsterAI _monsterAI;

		private Humanoid _humanoid;

		private bool _itemsHidden;

		private float _scanInterval = 2f;

		private float _timeSinceLastScan;

		private float _greetCooldown;

		private float _taskTimeout;

		private GameObject _targetObj;

		private string _currentTask = "Idle";

		private ItemData _heldItemData;

		private bool _weaponsCleared;

		private Dictionary<GameObject, float> _blacklistedObjects = new Dictionary<GameObject, float>();

		public static HashSet<ZDOID> ReservedItems = new HashSet<ZDOID>();

		private ZDOID _reservedZDOID = ZDOID.None;

		private Vector3 _lastPos;

		private float _stuckTimer;

		private bool _isSleeping;

		private bool _wasNight;

		private static readonly string[] _sleepPhrases = new string[8] { "Deu a minha hora, o peão tá cansado. Até amanhã!", "Chega por hoje, amanhã tem mais.", "Bati o ponto! Boa noite chefe.", "Indo deitar. Ninguém é de ferro, né?", "E chegou a hora de dormir, até amanhã!", "Acabou o expediente, patrão. Vou berçar.", "Vou capotar na cama agora. Boa noite!", "Sextou... ou não, mas eu vou dormir." };

		private static readonly string[] _wakePhrases = new string[4] { "Bom dia! Bora trabalhar que a base não se constrói sozinha.", "O sol nasceu, hora de arregaçar as mangas!", "Mais um dia de labuta. Bom dia chefe!", "Acordei! Cadê as fornalhas pra encher?" };

		private static Dictionary<string, float> _messageCooldowns = new Dictionary<string, float>();

		private GameObject _targetSmelter;

		private void Awake()
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			_nview = ((Component)this).GetComponent<ZNetView>();
			_character = ((Component)this).GetComponent<Character>();
			_monsterAI = ((Component)this).GetComponent<MonsterAI>();
			_humanoid = ((Component)this).GetComponent<Humanoid>();
			if ((Object)(object)_character != (Object)null)
			{
				_character.m_faction = (Faction)0;
			}
		}

		private void Start()
		{
			if ((Object)(object)_monsterAI != (Object)null)
			{
				_monsterAI.m_alertRange = 0f;
				((BaseAI)_monsterAI).m_viewRange = 0f;
				((BaseAI)_monsterAI).m_hearRange = 0f;
				((BaseAI)_monsterAI).m_afraidOfFire = false;
				((BaseAI)_monsterAI).m_avoidFire = false;
				_monsterAI.m_fleeIfNotAlerted = false;
			}
			if ((Object)(object)_nview != (Object)null && _nview.IsOwner() && (Object)(object)_monsterAI != (Object)null)
			{
				((BaseAI)_monsterAI).SetPatrolPoint();
				((BaseAI)_monsterAI).m_randomMoveRange = Plugin.WorkRadius.Value;
				((BaseAI)_monsterAI).m_randomMoveInterval = 5f;
			}
		}

		private void Update()
		{
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Invalid comparison between Unknown and I4
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Invalid comparison between Unknown and I4
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Invalid comparison between Unknown and I4
			if ((Object)(object)_nview == (Object)null || !_nview.IsOwner())
			{
				return;
			}
			if ((Object)(object)_character != (Object)null)
			{
				_character.m_walkSpeed = Plugin.NpcWalkSpeed.Value;
				_character.m_runSpeed = Plugin.NpcRunSpeed.Value;
			}
			if (!_weaponsCleared && (Object)(object)_humanoid != (Object)null && _humanoid.GetInventory() != null)
			{
				List<ItemData> list = new List<ItemData>(_humanoid.GetInventory().GetAllItems());
				if (list.Count > 0)
				{
					foreach (ItemData item in list)
					{
						if ((int)item.m_shared.m_itemType == 4 || (int)item.m_shared.m_itemType == 3 || (int)item.m_shared.m_itemType == 14 || item.m_shared.m_name.ToLower().Contains("crossbow") || item.m_shared.m_name.ToLower().Contains("arbalest"))
						{
							_humanoid.UnequipItem(item, true);
							_humanoid.GetInventory().RemoveItem(item);
						}
					}
					_weaponsCleared = true;
				}
			}
			if (_greetCooldown > 0f)
			{
				_greetCooldown -= Time.deltaTime;
			}
			if (!_itemsHidden && (Object)(object)_humanoid != (Object)null)
			{
				_humanoid.HideHandItems(false, true);
				_itemsHidden = true;
			}
			if ((Object)(object)_character != (Object)null)
			{
				if (_heldItemData != null && _heldItemData.m_stack > 0)
				{
					string arg = Localization.instance.Localize(_heldItemData.m_shared.m_name);
					_character.m_name = $"Assistente ({_heldItemData.m_stack}x {arg})";
				}
				else
				{
					_character.m_name = "Assistente da Base";
				}
			}
			_timeSinceLastScan += Time.deltaTime;
			if (_timeSinceLastScan >= _scanInterval)
			{
				_timeSinceLastScan = 0f;
				CheckForPlayerGreeting();
				ProcessAI();
			}
		}

		private void SayMessage(string msgId, string text, float cooldownMinutes = 3f, bool force = false)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			Player closestPlayer = Player.GetClosestPlayer(((Component)this).transform.position, 15f);
			if ((Object)(object)closestPlayer == (Object)null || (!force && _messageCooldowns.ContainsKey(msgId) && Time.time < _messageCooldowns[msgId]))
			{
				return;
			}
			AssistantAI[] array = Object.FindObjectsOfType<AssistantAI>();
			AssistantAI assistantAI = this;
			float num = Vector3.Distance(((Component)this).transform.position, ((Component)closestPlayer).transform.position);
			AssistantAI[] array2 = array;
			foreach (AssistantAI assistantAI2 in array2)
			{
				float num2 = Vector3.Distance(((Component)assistantAI2).transform.position, ((Component)closestPlayer).transform.position);
				if (num2 < num)
				{
					assistantAI = assistantAI2;
					num = num2;
				}
			}
			if (!((Object)(object)assistantAI != (Object)(object)this))
			{
				Chat.instance.SetNpcText(((Component)this).gameObject, Vector3.up * 1.5f, 20f, 5f, "", text, false);
				_messageCooldowns[msgId] = Time.time + cooldownMinutes * 60f;
			}
		}

		private void CheckForPlayerGreeting()
		{
			//IL_0013: 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)
			if (_greetCooldown <= 0f)
			{
				Player closestPlayer = Player.GetClosestPlayer(((Component)this).transform.position, 10f);
				if ((Object)(object)closestPlayer != (Object)null)
				{
					((Component)this).transform.LookAt(((Component)closestPlayer).transform.position);
					SayMessage("greet", "Olá " + closestPlayer.GetPlayerName() + ", trabalhando duro na base!", 5f);
					_greetCooldown = 60f;
				}
			}
		}

		private GameObject FindBed()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			List<Piece> list = new List<Piece>();
			Piece.GetAllPiecesInRadius(GetBaseCenter(), 15f, list);
			foreach (Piece item in list)
			{
				if (((Object)item).name.StartsWith("BaseAssistantBed") || item.m_name.Contains("Cama do Assistente"))
				{
					return ((Component)item).gameObject;
				}
			}
			return null;
		}

		private GameObject FindTotem()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			List<Piece> list = new List<Piece>();
			Piece.GetAllPiecesInRadius(GetBaseCenter(), 5f, list);
			foreach (Piece item in list)
			{
				if (((Object)item).name.StartsWith("AssistantTotem") || (Object)(object)((Component)item).GetComponent<AssistantSpawner>() != (Object)null)
				{
					return ((Component)item).gameObject;
				}
			}
			return null;
		}

		private void ReleaseReservation()
		{
			//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_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			if (_reservedZDOID != ZDOID.None)
			{
				ReservedItems.Remove(_reservedZDOID);
				_reservedZDOID = ZDOID.None;
			}
		}

		private void ClearReservationWithoutRelease()
		{
			//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)
			_reservedZDOID = ZDOID.None;
		}

		private void SetTask(string task, GameObject target)
		{
			if (task != _currentTask)
			{
				ReleaseReservation();
			}
			_currentTask = task;
			_targetObj = target;
			_taskTimeout = 15f;
			_stuckTimer = 0f;
			if ((Object)(object)_monsterAI != (Object)null)
			{
				_monsterAI.SetFollowTarget(target);
			}
		}

		private void ProcessAI()
		{
			//IL_0130: 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_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01da: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0225: Unknown result type (might be due to invalid IL or missing references)
			//IL_022a: Unknown result type (might be due to invalid IL or missing references)
			//IL_037e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0384: Unknown result type (might be due to invalid IL or missing references)
			//IL_0442: Unknown result type (might be due to invalid IL or missing references)
			//IL_0447: Unknown result type (might be due to invalid IL or missing references)
			bool flag = (Object)(object)EnvMan.instance != (Object)null && EnvMan.IsNight();
			if (flag && !_wasNight)
			{
				string text = _sleepPhrases[Random.Range(0, _sleepPhrases.Length)];
				SayMessage("night_start", text, 10f, force: true);
				_wasNight = true;
				GameObject val = FindBed();
				if ((Object)(object)val != (Object)null)
				{
					DropHoldingItem();
					SetTask("GoToSleep", val);
				}
				else
				{
					SayMessage("no_bed", "Trabalhei o dia todo e não me deram nem uma cama... Que exploração!", 10f, force: true);
					GameObject val2 = FindTotem();
					if ((Object)(object)val2 != (Object)null)
					{
						DropHoldingItem();
						SetTask("GoToSleep", val2);
					}
				}
			}
			else if (!flag && _wasNight)
			{
				string text2 = _wakePhrases[Random.Range(0, _wakePhrases.Length)];
				SayMessage("morning_start", text2, 10f, force: true);
				_wasNight = false;
				_isSleeping = false;
				SetTask("Idle", null);
				GameObject val3 = FindBed();
				if ((Object)(object)val3 != (Object)null)
				{
					((Component)this).transform.position = val3.transform.position + val3.transform.forward * 1.5f + Vector3.up * 0.5f;
				}
				else
				{
					GameObject val4 = FindTotem();
					if ((Object)(object)val4 != (Object)null)
					{
						((Component)this).transform.position = val4.transform.position + val4.transform.forward * 1.5f + Vector3.up * 0.5f;
					}
					else
					{
						((Component)this).transform.position = GetBaseCenter() + ((Component)this).transform.forward * 1.5f + Vector3.up * 0.5f;
					}
				}
				GameObject prefab = Cache.GetPrefab<GameObject>("vfx_sledge_hit");
				if ((Object)(object)prefab != (Object)null)
				{
					Object.Instantiate<GameObject>(prefab, ((Component)this).transform.position, Quaternion.identity);
				}
			}
			if (_isSleeping && flag)
			{
				return;
			}
			if (IsUnderAttack())
			{
				if (_currentTask != "Panic")
				{
					SetTask("Panic", null);
					SayMessage("panic_start", "Socorro! Monstros na base!", 5f, force: true);
				}
				GameObject val5 = FindBed();
				if ((Object)(object)val5 != (Object)null)
				{
					_monsterAI.SetFollowTarget(val5);
					return;
				}
				GameObject val6 = FindTotem();
				if ((Object)(object)val6 != (Object)null)
				{
					_monsterAI.SetFollowTarget(val6);
				}
				else
				{
					_monsterAI.SetFollowTarget((GameObject)null);
				}
				return;
			}
			if (_currentTask == "Panic")
			{
				SetTask("Idle", null);
				SayMessage("panic_end", "Ufa, parece seguro agora...", 5f, force: true);
			}
			if (_isSleeping)
			{
				return;
			}
			if (_wasNight && _currentTask == "Idle")
			{
				GameObject val7 = FindBed();
				if ((Object)(object)val7 != (Object)null)
				{
					SetTask("GoToSleep", val7);
					return;
				}
				GameObject val8 = FindTotem();
				if ((Object)(object)val8 != (Object)null)
				{
					SetTask("GoToSleep", val8);
				}
				return;
			}
			if (_currentTask != "Idle")
			{
				if (Vector3.Distance(((Component)this).transform.position, _lastPos) < 0.5f)
				{
					_stuckTimer += _scanInterval;
					if (_stuckTimer >= Plugin.StuckTimeout.Value && (Object)(object)_targetObj != (Object)null)
					{
						Logger.LogInfo((object)("[AssistantAI] Preso indo para " + ((Object)_targetObj).name + ". Abandonando tarefa!"));
						float num = ((_currentTask == "PickupGround") ? 5f : 15f);
						_blacklistedObjects[_targetObj] = Time.time + num;
						SetTask("Idle", null);
						return;
					}
				}
				else
				{
					_stuckTimer = 0f;
				}
				_lastPos = ((Component)this).transform.position;
				_taskTimeout -= _scanInterval;
				if ((Object)(object)_targetObj == (Object)null || _taskTimeout <= 0f)
				{
					if ((Object)(object)_targetObj == (Object)null && _currentTask == "PickupGround")
					{
						ClearReservationWithoutRelease();
					}
					Logger.LogWarning((object)("[AssistantAI] Tarefa " + _currentTask + " expirou ou alvo foi destruído. Voltando para Idle."));
					SetTask("Idle", null);
					return;
				}
			}
			string currentTask = _currentTask;
			if (_currentTask == "Idle")
			{
				FindNewTask();
			}
			else if (_currentTask == "PickupGround")
			{
				ExecutePickupGround();
			}
			else if (_currentTask == "TakeFromInbox")
			{
				ExecuteTakeFromInbox();
			}
			else if (_currentTask == "MoveToChestToStore")
			{
				ExecuteStoreToChest();
			}
			else if (_currentTask == "MoveToChestToFetch")
			{
				ExecuteFetchForSmelting();
			}
			else if (_currentTask == "MoveToChestToConsolidate")
			{
				ExecuteConsolidateFetch();
			}
			else if (_currentTask == "FeedSmelter")
			{
				ExecuteFeedSmelter();
			}
			else if (_currentTask == "RepairPiece")
			{
				ExecuteRepairPiece();
			}
			else if (_currentTask == "GoToSleep")
			{
				ExecuteGoToSleep();
			}
			if (currentTask != _currentTask)
			{
				Logger.LogInfo((object)("[AssistantAI] Mudou de tarefa: " + currentTask + " -> " + _currentTask));
			}
		}

		private Vector3 GetBaseCenter()
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: 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_0043: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_nview != (Object)null && _nview.GetZDO() != null)
			{
				Vector3 vec = _nview.GetZDO().GetVec3("HomeBedPos", Vector3.zero);
				if (vec != Vector3.zero)
				{
					return vec;
				}
			}
			return ((Component)this).transform.position;
		}

		private bool CheckAndSetSmeltingTask(Collider[] hits)
		{
			for (int i = 0; i < hits.Length; i++)
			{
				Smelter componentInParent = ((Component)hits[i]).GetComponentInParent<Smelter>();
				if (!((Object)(object)componentInParent != (Object)null) || (_blacklistedObjects.ContainsKey(((Component)componentInParent).gameObject) && Time.time < _blacklistedObjects[((Component)componentInParent).gameObject]))
				{
					continue;
				}
				ZNetView component = ((Component)componentInParent).GetComponent<ZNetView>();
				if ((Object)(object)component == (Object)null || !component.IsValid())
				{
					continue;
				}
				if (componentInParent.m_maxFuel > 0 && (Object)(object)componentInParent.m_fuelItem != (Object)null && component.GetZDO().GetFloat("fuel", 0f) < (float)componentInParent.m_maxFuel)
				{
					string name = componentInParent.m_fuelItem.m_itemData.m_shared.m_name;
					int leaveAmount = (name.ToLower().Contains("coal") ? Plugin.LeaveCoalAmount.Value : Plugin.LeaveWoodAmount.Value);
					Container val = FindChestForSmelterItem(hits, name, leaveAmount);
					if ((Object)(object)val != (Object)null)
					{
						_heldItemData = componentInParent.m_fuelItem.m_itemData.Clone();
						_heldItemData.m_dropPrefab = ((Component)componentInParent.m_fuelItem).gameObject;
						_heldItemData.m_stack = 0;
						_targetSmelter = ((Component)componentInParent).gameObject;
						SetTask("MoveToChestToFetch", ((Component)val).gameObject);
						return true;
					}
					string text = (name.ToLower().Contains("coal") ? "Carvão" : "Madeira para queimar");
					SayMessage("no_fuel_" + name, "Atenção chefe! Falta " + text + " nos baús!", 5f);
				}
				if (component.GetZDO().GetInt("queued", 0) >= componentInParent.m_maxOre || componentInParent.m_conversion == null)
				{
					continue;
				}
				foreach (ItemConversion item in componentInParent.m_conversion)
				{
					if ((Object)(object)item.m_from == (Object)null || (Object)(object)item.m_to == (Object)null)
					{
						continue;
					}
					string name2 = item.m_from.m_itemData.m_shared.m_name;
					string name3 = item.m_to.m_itemData.m_shared.m_name;
					if (name3.ToLower().Contains("coal"))
					{
						string text2 = name2.ToLower();
						if (text2.Contains("finewood") || text2.Contains("roundlog") || text2.Contains("elderbark") || text2.Contains("yggdrasil"))
						{
							continue;
						}
					}
					int num = CountItemInBase(name3, hits);
					int num2 = (name3.ToLower().Contains("coal") ? Plugin.MaxCoalAmount.Value : Plugin.MaxSmeltedMetal.Value);
					if (num < num2)
					{
						int leaveAmount2 = (name2.ToLower().Contains("wood") ? Plugin.LeaveWoodAmount.Value : Plugin.LeaveOreAmount.Value);
						Container val2 = FindChestForSmelterItem(hits, name2, leaveAmount2);
						if ((Object)(object)val2 != (Object)null)
						{
							_heldItemData = item.m_from.m_itemData.Clone();
							_heldItemData.m_dropPrefab = ((Component)item.m_from).gameObject;
							_heldItemData.m_stack = 0;
							_targetSmelter = ((Component)componentInParent).gameObject;
							SetTask("MoveToChestToFetch", ((Component)val2).gameObject);
							return true;
						}
					}
				}
			}
			return false;
		}

		private Container FindChestForSmelterItem(Collider[] hits, string targetItemName, int leaveAmount)
		{
			for (int i = 0; i < hits.Length; i++)
			{
				Container componentInParent = ((Component)hits[i]).GetComponentInParent<Container>();
				if ((Object)(object)componentInParent != (Object)null && componentInParent.GetInventory() != null && (!_blacklistedObjects.ContainsKey(((Component)componentInParent).gameObject) || !(Time.time < _blacklistedObjects[((Component)componentInParent).gameObject])) && componentInParent.GetInventory().CountItems(targetItemName, -1, true) > leaveAmount)
				{
					return componentInParent;
				}
			}
			return null;
		}

		private void ExecuteGoToSleep()
		{
			if ((Object)(object)_targetObj == (Object)null)
			{
				_currentTask = "Idle";
				return;
			}
			float num = 3f;
			if (IsCloseEnough(_targetObj, num, num))
			{
				_isSleeping = true;
				_currentTask = "Idle";
				_monsterAI.SetFollowTarget((GameObject)null);
			}
			else
			{
				_monsterAI.SetFollowTarget(_targetObj);
			}
		}

		private void ExecuteRepairPiece()
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_targetObj == (Object)null)
			{
				_currentTask = "Idle";
				return;
			}
			float value = Plugin.RepairDistance.Value;
			if (IsCloseEnough(_targetObj, value, value))
			{
				Collider[] array = Physics.OverlapSphere(_targetObj.transform.position, Plugin.AoERepairRadius.Value);
				bool flag = false;
				Collider[] array2 = array;
				for (int i = 0; i < array2.Length; i++)
				{
					Piece componentInParent = ((Component)array2[i]).GetComponentInParent<Piece>();
					if ((Object)(object)componentInParent != (Object)null)
					{
						WearNTear component = ((Component)componentInParent).GetComponent<WearNTear>();
						if ((Object)(object)component != (Object)null && component.GetHealthPercentage() < 1f)
						{
							component.Repair();
							componentInParent.m_placeEffect.Create(((Component)componentInParent).transform.position, ((Component)componentInParent).transform.rotation, (Transform)null, 1f, -1);
							flag = true;
						}
					}
				}
				if (flag)
				{
					((Component)this).transform.LookAt(_targetObj.transform.position);
					ZSyncAnimation component2 = ((Component)this).GetComponent<ZSyncAnimation>();
					if ((Object)(object)component2 != (Object)null)
					{
						component2.SetTrigger("interact");
					}
				}
				_currentTask = "Idle";
				_monsterAI.SetFollowTarget((GameObject)null);
			}
			else
			{
				_monsterAI.SetFollowTarget(_targetObj);
			}
		}

		private int CountItemInBase(string prefabName, Collider[] hits)
		{
			GameObject prefab = Cache.GetPrefab<GameObject>(prefabName);
			if ((Object)(object)prefab == (Object)null)
			{
				return 0;
			}
			string name = prefab.GetComponent<ItemDrop>().m_itemData.m_shared.m_name;
			int num = 0;
			foreach (Collider val in hits)
			{
				Container componentInParent = ((Component)val).GetComponentInParent<Container>();
				if ((Object)(object)componentInParent != (Object)null && componentInParent.GetInventory() != null && !((Object)componentInParent).name.Contains("personal"))
				{
					num += componentInParent.GetInventory().CountItems(name, -1, true);
					continue;
				}
				ItemDrop componentInParent2 = ((Component)val).GetComponentInParent<ItemDrop>();
				if ((Object)(object)componentInParent2 != (Object)null && componentInParent2.m_itemData != null && componentInParent2.m_itemData.m_shared.m_name == name)
				{
					num += componentInParent2.m_itemData.m_stack;
					continue;
				}
				AssistantAI componentInParent3 = ((Component)val).GetComponentInParent<AssistantAI>();
				if ((Object)(object)componentInParent3 != (Object)null && componentInParent3._heldItemData != null && componentInParent3._heldItemData.m_shared.m_name == name)
				{
					num += componentInParent3._heldItemData.m_stack;
				}
			}
			return num;
		}

		private void FindNewTask()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0337: Unknown result type (might be due to invalid IL or missing references)
			//IL_033c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0343: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_03af: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ba: Unknown result type (might be due to invalid IL or missing references)
			Collider[] array = Physics.OverlapSphere(GetBaseCenter(), Plugin.WorkRadius.Value);
			if (_heldItemData != null && _heldItemData.m_stack > 0)
			{
				GameObject dropPrefab = _heldItemData.m_dropPrefab;
				int num = 50;
				if ((Object)(object)dropPrefab != (Object)null)
				{
					num = dropPrefab.GetComponent<ItemDrop>().m_itemData.m_shared.m_maxStackSize;
				}
				if (_heldItemData.m_stack < num)
				{
					Collider[] array2 = array;
					for (int i = 0; i < array2.Length; i++)
					{
						ItemDrop componentInParent = ((Component)array2[i]).GetComponentInParent<ItemDrop>();
						if (!((Object)(object)componentInParent != (Object)null) || !((Object)(object)((Component)componentInParent).GetComponent<ZNetView>() != (Object)null) || !((Component)componentInParent).GetComponent<ZNetView>().IsValid())
						{
							continue;
						}
						ZDOID uid = ((Component)componentInParent).GetComponent<ZNetView>().GetZDO().m_uid;
						if (!ReservedItems.Contains(uid) && (!_blacklistedObjects.ContainsKey(((Component)componentInParent).gameObject) || !(Time.time < _blacklistedObjects[((Component)componentInParent).gameObject])))
						{
							string text = ((Object)((Component)componentInParent).gameObject).name.Replace("(Clone)", "").Trim();
							if ((Object)(object)dropPrefab != (Object)null && text == ((Object)dropPrefab).name)
							{
								SetTask("PickupGround", ((Component)componentInParent).gameObject);
								ReservedItems.Add(uid);
								_reservedZDOID = uid;
								return;
							}
						}
					}
				}
				Container val = FindChestFor(_heldItemData, array);
				if ((Object)(object)val != (Object)null)
				{
					SetTask("MoveToChestToStore", ((Component)val).gameObject);
					return;
				}
				Logger.LogWarning((object)("[AssistantAI] Não achei baú com espaço para " + ((Object)_heldItemData.m_dropPrefab).name + ". Dropando no chão."));
				DropHoldingItem();
				return;
			}
			if (Plugin.EnableSorting.Value)
			{
				Container val2 = FindInboxChestWithValidItems();
				if ((Object)(object)val2 != (Object)null)
				{
					_currentTask = "TakeFromInbox";
					_targetObj = ((Component)val2).gameObject;
					_monsterAI.SetFollowTarget(_targetObj);
					return;
				}
			}
			if (Plugin.EnableRepairing.Value)
			{
				Collider[] array2 = array;
				for (int i = 0; i < array2.Length; i++)
				{
					Piece componentInParent2 = ((Component)array2[i]).GetComponentInParent<Piece>();
					if ((Object)(object)componentInParent2 != (Object)null && (!_blacklistedObjects.ContainsKey(((Component)componentInParent2).gameObject) || !(Time.time < _blacklistedObjects[((Component)componentInParent2).gameObject])))
					{
						WearNTear component = ((Component)componentInParent2).GetComponent<WearNTear>();
						if ((Object)(object)component != (Object)null && component.GetHealthPercentage() < Plugin.RepairHealthThreshold.Value)
						{
							SetTask("RepairPiece", ((Component)componentInParent2).gameObject);
							return;
						}
					}
				}
			}
			if (Plugin.EnableSmelting.Value && CheckAndSetSmeltingTask(array))
			{
				return;
			}
			if (Plugin.EnableLooting.Value)
			{
				Collider[] array2 = array;
				for (int i = 0; i < array2.Length; i++)
				{
					ItemDrop componentInParent3 = ((Component)array2[i]).GetComponentInParent<ItemDrop>();
					if ((Object)(object)componentInParent3 != (Object)null && (Object)(object)((Component)componentInParent3).GetComponent<ZNetView>() != (Object)null && ((Component)componentInParent3).GetComponent<ZNetView>().IsValid())
					{
						ZDOID uid2 = ((Component)componentInParent3).GetComponent<ZNetView>().GetZDO().m_uid;
						if (!ReservedItems.Contains(uid2) && (!_blacklistedObjects.ContainsKey(((Component)componentInParent3).gameObject) || !(Time.time < _blacklistedObjects[((Component)componentInParent3).gameObject])) && componentInParent3.m_itemData != null && (Object)(object)FindChestFor(componentInParent3.m_itemData, array) != (Object)null)
						{
							SetTask("PickupGround", ((Component)componentInParent3).gameObject);
							ReservedItems.Add(uid2);
							_reservedZDOID = uid2;
							return;
						}
					}
				}
			}
			if (!Plugin.EnableSorting.Value || !CheckAndSetConsolidationTask(array))
			{
				SayMessage("all_done", "Base 100% limpa e organizada. Pausa para o hidromel!", 60f);
			}
		}

		private Container FindChestFor(ItemData targetItem, Collider[] hits)
		{
			if (targetItem == null || targetItem.m_shared == null)
			{
				return null;
			}
			Container result = null;
			int num = -1;
			for (int i = 0; i < hits.Length; i++)
			{
				Container componentInParent = ((Component)hits[i]).GetComponentInParent<Container>();
				if ((Object)(object)componentInParent != (Object)null && componentInParent.GetInventory() != null && !((Object)componentInParent).name.Contains("personal") && (!_blacklistedObjects.ContainsKey(((Component)componentInParent).gameObject) || !(Time.time < _blacklistedObjects[((Component)componentInParent).gameObject])) && componentInParent.GetInventory().CanAddItem(targetItem, -1))
				{
					string customName = "";
					ZNetView component = ((Component)componentInParent).GetComponent<ZNetView>();
					if ((Object)(object)component != (Object)null && component.IsValid() && component.GetZDO() != null)
					{
						customName = component.GetZDO().GetString("text", "").ToLower()
							.Trim();
					}
					int chestScore = GetChestScore(componentInParent, targetItem, customName);
					if (chestScore > num)
					{
						num = chestScore;
						result = componentInParent;
					}
				}
			}
			if (num < 0)
			{
				return null;
			}
			return result;
		}

		private int GetChestScore(Container container, ItemData targetItem, string customName)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Invalid comparison between Unknown and I4
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: Unknown result type (might be due to invalid IL or missing references)
			string text = targetItem.m_shared.m_name ?? "";
			string text2 = text.ToLower();
			ItemType itemType = targetItem.m_shared.m_itemType;
			if (!string.IsNullOrEmpty(customName))
			{
				if (MatchAny(customName, Plugin.TagIgnore.Value.ToLower().Split(new char[1] { ',' })))
				{
					return -1000;
				}
				string text3 = Localization.instance.Localize(text).ToLower().Trim();
				if (customName == text3)
				{
					return 2000;
				}
				if (customName == text2.Replace("$item_", ""))
				{
					return 2000;
				}
				bool flag = false;
				if (MatchAny(customName, Plugin.TagWeapons.Value.ToLower().Split(new char[1] { ',' })) && IsWeapon(itemType))
				{
					flag = true;
				}
				if (MatchAny(customName, Plugin.TagArmor.Value.ToLower().Split(new char[1] { ',' })) && IsArmor(itemType))
				{
					flag = true;
				}
				if (MatchAny(customName, Plugin.TagFood.Value.ToLower().Split(new char[1] { ',' })) && (int)itemType == 2)
				{
					flag = true;
				}
				if (MatchAny(customName, Plugin.TagWood.Value.ToLower().Split(new char[1] { ',' })) && IsWood(text2, itemType))
				{
					flag = true;
				}
				if (MatchAny(customName, Plugin.TagMetal.Value.ToLower().Split(new char[1] { ',' })) && IsMetal(text2, itemType))
				{
					flag = true;
				}
				if (!flag)
				{
					return -1000;
				}
				return 1000;
			}
			if (container.GetInventory().NrOfItems() == 0)
			{
				return 0;
			}
			bool flag2 = false;
			bool flag3 = false;
			foreach (ItemData allItem in container.GetInventory().GetAllItems())
			{
				if (allItem != null && allItem.m_shared != null)
				{
					if ((allItem.m_shared.m_name?.ToLower() ?? "") == text2)
					{
						flag3 = true;
					}
					else
					{
						flag2 = true;
					}
				}
			}
			if (flag2)
			{
				return -1000;
			}
			if (flag3)
			{
				return 100;
			}
			return -1000;
		}

		private bool CheckAndSetConsolidationTask(Collider[] hits)
		{
			for (int i = 0; i < hits.Length; i++)
			{
				Container componentInParent = ((Component)hits[i]).GetComponentInParent<Container>();
				if ((Object)(object)componentInParent == (Object)null || componentInParent.GetInventory() == null || ((Object)componentInParent).name.Contains("personal") || (_blacklistedObjects.ContainsKey(((Component)componentInParent).gameObject) && Time.time < _blacklistedObjects[((Component)componentInParent).gameObject]))
				{
					continue;
				}
				string customName = "";
				ZNetView component = ((Component)componentInParent).GetComponent<ZNetView>();
				if ((Object)(object)component != (Object)null && component.IsValid() && component.GetZDO() != null)
				{
					customName = component.GetZDO().GetString("text", "").ToLower()
						.Trim();
				}
				foreach (ItemData allItem in componentInParent.GetInventory().GetAllItems())
				{
					if (allItem == null || allItem.m_shared == null || (Object)(object)allItem.m_dropPrefab == (Object)null)
					{
						continue;
					}
					int chestScore = GetChestScore(componentInParent, allItem, customName);
					if (chestScore >= 2000)
					{
						continue;
					}
					Container val = FindChestFor(allItem, hits);
					if ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)componentInParent)
					{
						string customName2 = "";
						ZNetView component2 = ((Component)val).GetComponent<ZNetView>();
						if ((Object)(object)component2 != (Object)null && component2.IsValid() && component2.GetZDO() != null)
						{
							customName2 = component2.GetZDO().GetString("text", "").ToLower()
								.Trim();
						}
						int chestScore2 = GetChestScore(val, allItem, customName2);
						if (chestScore2 >= 1000 && chestScore2 > chestScore)
						{
							_heldItemData = allItem.Clone();
							_heldItemData.m_stack = 0;
							SetTask("MoveToChestToConsolidate", ((Component)componentInParent).gameObject);
							return true;
						}
					}
				}
			}
			return false;
		}

		private bool MatchAny(string text, string[] tags)
		{
			foreach (string text2 in tags)
			{
				if (text2.Trim() != "" && text.Contains(text2.Trim()))
				{
					return true;
				}
			}
			return false;
		}

		private bool IsWeapon(ItemType t)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Invalid comparison between Unknown and I4
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Invalid comparison between Unknown and I4
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Invalid comparison between Unknown and I4
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Invalid comparison between Unknown and I4
			if ((int)t != 3 && (int)t != 14 && (int)t != 4)
			{
				return (int)t == 19;
			}
			return true;
		}

		private bool IsArmor(ItemType t)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Invalid comparison between Unknown and I4
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Invalid comparison between Unknown and I4
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Invalid comparison between Unknown and I4
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Invalid comparison between Unknown and I4
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Invalid comparison between Unknown and I4
			if ((int)t != 5 && (int)t != 6 && (int)t != 7 && (int)t != 11)
			{
				return (int)t == 17;
			}
			return true;
		}

		private bool IsWood(string name, ItemType type)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Invalid comparison between Unknown and I4
			if ((int)type != 1)
			{
				return false;
			}
			if (!name.Contains("wood") && !name.Contains("log") && !name.Contains("bark") && !name.Contains("madeira"))
			{
				return name.Contains("lenha");
			}
			return true;
		}

		private bool IsMetal(string name, ItemType type)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Invalid comparison between Unknown and I4
			if ((int)type != 1)
			{
				return false;
			}
			if (!name.Contains("ore") && !name.Contains("scrap") && !name.Contains("copper") && !name.Contains("iron") && !name.Contains("silver") && !name.Contains("tin") && !name.Contains("bronze") && !name.Contains("metal"))
			{
				return name.Contains("flametal");
			}
			return true;
		}

		private Container FindChestForWood(Collider[] hits, out string foundWoodType)
		{
			foundWoodType = "Wood";
			GameObject prefab = Cache.GetPrefab<GameObject>("Wood");
			if ((Object)(object)prefab == (Object)null)
			{
				return null;
			}
			string name = prefab.GetComponent<ItemDrop>().m_itemData.m_shared.m_name;
			for (int i = 0; i < hits.Length; i++)
			{
				Container componentInParent = ((Component)hits[i]).GetComponentInParent<Container>();
				if ((Object)(object)componentInParent != (Object)null && componentInParent.GetInventory() != null && !((Object)componentInParent).name.Contains("personal") && (!_blacklistedObjects.ContainsKey(((Component)componentInParent).gameObject) || !(Time.time < _blacklistedObjects[((Component)componentInParent).gameObject])) && componentInParent.GetInventory().CountItems(name, -1, true) > 0)
				{
					return componentInParent;
				}
			}
			foundWoodType = "";
			return null;
		}

		private bool IsCloseEnough(GameObject target, float maxDistXZ = 1.5f, float maxDistY = 2f)
		{
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: 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_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: 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_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)target == (Object)null)
			{
				return false;
			}
			maxDistXZ += 3.5f;
			maxDistY += 3.5f;
			Collider[] componentsInChildren = target.GetComponentsInChildren<Collider>();
			if (componentsInChildren.Length != 0)
			{
				float num = float.MaxValue;
				float num2 = float.MaxValue;
				Collider[] array = componentsInChildren;
				foreach (Collider val in array)
				{
					if (!val.isTrigger)
					{
						Bounds bounds = val.bounds;
						Vector3 val2 = ((Bounds)(ref bounds)).ClosestPoint(((Component)this).transform.position);
						float num3 = Vector2.Distance(new Vector2(((Component)this).transform.position.x, ((Component)this).transform.position.z), new Vector2(val2.x, val2.z));
						float num4 = Mathf.Abs(((Component)this).transform.position.y - val2.y);
						if (num3 < num)
						{
							num = num3;
						}
						if (num4 < num2)
						{
							num2 = num4;
						}
					}
				}
				if (num != float.MaxValue)
				{
					Logger.LogInfo((object)$"[AssistantAI] Alvo: {((Object)target).name} | Dist Atual -> XZ: {num:F2} / Y: {num2:F2} | Config -> XZ: {maxDistXZ:F2} / Y: {maxDistY:F2}");
					if (num < maxDistXZ)
					{
						return num2 < maxDistY;
					}
					return false;
				}
			}
			float num5 = Vector2.Distance(new Vector2(((Component)this).transform.position.x, ((Component)this).transform.position.z), new Vector2(target.transform.position.x, target.transform.position.z));
			float num6 = Mathf.Abs(((Component)this).transform.position.y - target.transform.position.y);
			Logger.LogInfo((object)$"[AssistantAI] Alvo (Sem Colisão): {((Object)target).name} | Dist Atual -> XZ: {num5:F2} / Y: {num6:F2} | Config -> XZ: {maxDistXZ + 2f:F2} / Y: {maxDistY + 0.5f:F2}");
			if (num5 < maxDistXZ + 2f)
			{
				return num6 < maxDistY + 0.5f;
			}
			return false;
		}

		private void ExecutePickupGround()
		{
			float value = Plugin.GroundItemDistance.Value;
			if (IsCloseEnough(_targetObj, value, value))
			{
				ItemDrop component = _targetObj.GetComponent<ItemDrop>();
				if ((Object)(object)component != (Object)null && component.m_itemData != null)
				{
					if (_heldItemData == null)
					{
						_heldItemData = component.m_itemData.Clone();
					}
					else if (((Object)_heldItemData.m_dropPrefab).name == ((Object)component.m_itemData.m_dropPrefab).name)
					{
						ItemData heldItemData = _heldItemData;
						heldItemData.m_stack += component.m_itemData.m_stack;
					}
					ZSyncAnimation component2 = ((Component)this).GetComponent<ZSyncAnimation>();
					if ((Object)(object)component2 != (Object)null)
					{
						component2.SetTrigger("interact");
					}
					if ((Object)(object)((Component)component).GetComponent<ZNetView>() != (Object)null)
					{
						((Component)component).GetComponent<ZNetView>().Destroy();
					}
					else
					{
						Object.Destroy((Object)(object)((Component)component).gameObject);
					}
					ClearReservationWithoutRelease();
					SetTask("Idle", null);
				}
			}
			else
			{
				_monsterAI.SetFollowTarget(_targetObj);
			}
		}

		private void ExecuteStoreToChest()
		{
			//IL_03c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_023f: Unknown result type (might be due to invalid IL or missing references)
			//IL_024f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0266: Unknown result type (might be due to invalid IL or missing references)
			//IL_0276: Unknown result type (might be due to invalid IL or missing references)
			float value = Plugin.ChestDistance.Value;
			if (IsCloseEnough(_targetObj, value, value))
			{
				Container component = _targetObj.GetComponent<Container>();
				if ((Object)(object)component != (Object)null && component.GetInventory() != null && _heldItemData != null)
				{
					int stack = _heldItemData.m_stack;
					bool flag = component.GetInventory().NrOfItems() == 0;
					string name = _heldItemData.m_shared.m_name;
					string text = Localization.instance.Localize(name).Trim();
					if (!string.IsNullOrEmpty(text))
					{
						text = char.ToUpper(text[0]) + text.Substring(1);
					}
					((Component)component).GetComponent<ZNetView>().ClaimOwnership();
					while (_heldItemData.m_stack > 0)
					{
						ItemData val = _heldItemData.Clone();
						val.m_stack = 1;
						if (!component.GetInventory().CanAddItem(val, -1))
						{
							break;
						}
						component.GetInventory().AddItem(val);
						ItemData heldItemData = _heldItemData;
						heldItemData.m_stack--;
					}
					if (stack != _heldItemData.m_stack)
					{
						if (flag && Plugin.EnableAutoLabeling.Value)
						{
							ZNetView component2 = ((Component)component).GetComponent<ZNetView>();
							if ((Object)(object)component2 != (Object)null && component2.IsValid())
							{
								component2.GetZDO().Set("text", text);
								Logger.LogInfo((object)("[AssistantAI] Auto-Labeling: Baú batizado como '" + text + "'"));
								string text2 = name.ToLower();
								if (IsWood(text2, _heldItemData.m_shared.m_itemType) || IsMetal(text2, _heldItemData.m_shared.m_itemType) || text2.Contains("stone") || text2.Contains("coal"))
								{
									Collider[] array = Physics.OverlapSphere(((Component)component).transform.position, 2.5f);
									for (int i = 0; i < array.Length; i++)
									{
										Container componentInParent = ((Component)array[i]).GetComponentInParent<Container>();
										if (!((Object)(object)componentInParent != (Object)null) || !((Object)(object)componentInParent != (Object)(object)component) || componentInParent.GetInventory() == null)
										{
											continue;
										}
										float num = Mathf.Abs(((Component)componentInParent).transform.position.x - ((Component)component).transform.position.x);
										float num2 = Mathf.Abs(((Component)componentInParent).transform.position.z - ((Component)component).transform.position.z);
										if (num < 0.5f && num2 < 0.5f && componentInParent.GetInventory().NrOfItems() == 0)
										{
											ZNetView component3 = ((Component)componentInParent).GetComponent<ZNetView>();
											if ((Object)(object)component3 != (Object)null && component3.IsValid() && string.IsNullOrEmpty(component3.GetZDO().GetString("text", "")))
											{
												component3.ClaimOwnership();
												component3.GetZDO().Set("text", text);
											}
										}
									}
								}
							}
						}
						ZSyncAnimation component4 = ((Component)this).GetComponent<ZSyncAnimation>();
						if ((Object)(object)component4 != (Object)null)
						{
							component4.SetTrigger("interact");
						}
						component.SetInUse(true);
						((MonoBehaviour)this).StartCoroutine(CloseChest(component));
					}
					if (_heldItemData.m_stack == 0)
					{
						_heldItemData = null;
						SetTask("Idle", null);
					}
					else
					{
						Logger.LogInfo((object)$"[AssistantAI] O baú encheu, sobrou {_heldItemData.m_stack} {((Object)_heldItemData.m_dropPrefab).name} na mão.");
						_blacklistedObjects[((Component)component).gameObject] = Time.time + 120f;
						SetTask("Idle", null);
					}
					((Component)this).transform.LookAt(((Component)component).transform.position);
				}
				else
				{
					DropHoldingItem();
				}
			}
			else
			{
				_monsterAI.SetFollowTarget(_targetObj);
			}
		}

		private IEnumerator CloseChest(Container chest)
		{
			yield return (object)new WaitForSeconds(1.5f);
			if ((Object)(object)chest != (Object)null)
			{
				chest.SetInUse(false);
			}
		}

		private void DropHoldingItem()
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			if (_heldItemData != null && _heldItemData.m_stack > 0)
			{
				ItemDrop.DropItem(_heldItemData, _heldItemData.m_stack, ((Component)this).transform.position + ((Component)this).transform.forward * 1f + Vector3.up * 0.5f, Quaternion.identity);
				_heldItemData = null;
				SetTask("Idle", null);
			}
		}

		private void ExecuteConsolidateFetch()
		{
			float value = Plugin.ChestDistance.Value;
			if (IsCloseEnough(_targetObj, value, value))
			{
				Container component = _targetObj.GetComponent<Container>();
				if ((Object)(object)component != (Object)null && component.GetInventory() != null && _heldItemData != null)
				{
					string name = _heldItemData.m_shared.m_name;
					int num = component.GetInventory().CountItems(name, -1, true);
					if (num > 0)
					{
						int num2 = Mathf.Min(_heldItemData.m_shared.m_maxStackSize, num);
						((Component)component).GetComponent<ZNetView>().ClaimOwnership();
						component.GetInventory().RemoveItem(name, num2, -1, true);
						component.SetInUse(true);
						((MonoBehaviour)this).StartCoroutine(CloseChest(component));
						_heldItemData.m_stack = num2;
						Logger.LogInfo((object)$"[AssistantAI] Saquei {_heldItemData.m_stack} {((Object)_heldItemData.m_dropPrefab).name} para organizar/descontaminar.");
					}
				}
				SetTask("Idle", null);
			}
			else
			{
				_monsterAI.SetFollowTarget(_targetObj);
			}
		}

		private void ExecuteFetchForSmelting()
		{
			float value = Plugin.ChestDistance.Value;
			if (IsCloseEnough(_targetObj, value, value))
			{
				Container component = _targetObj.GetComponent<Container>();
				if ((Object)(object)component != (Object)null && component.GetInventory() != null && _heldItemData != null)
				{
					string name = _heldItemData.m_shared.m_name;
					int num = component.GetInventory().CountItems(name, -1, true);
					int num2 = (name.ToLower().Contains("wood") ? Plugin.LeaveWoodAmount.Value : (name.ToLower().Contains("coal") ? Plugin.LeaveCoalAmount.Value : Plugin.LeaveOreAmount.Value));
					if (num > num2)
					{
						int num3 = Mathf.Min(10, num - num2);
						((Component)component).GetComponent<ZNetView>().ClaimOwnership();
						component.GetInventory().RemoveItem(name, num3, -1, true);
						component.SetInUse(true);
						((MonoBehaviour)this).StartCoroutine(CloseChest(component));
						ZSyncAnimation component2 = ((Component)this).GetComponent<ZSyncAnimation>();
						if ((Object)(object)component2 != (Object)null)
						{
							component2.SetTrigger("interact");
						}
						_heldItemData.m_stack = num3;
						if ((Object)(object)_targetSmelter != (Object)null)
						{
							SetTask("FeedSmelter", _targetSmelter);
							return;
						}
					}
				}
				SetTask("Idle", null);
			}
			else
			{
				_monsterAI.SetFollowTarget(_targetObj);
			}
		}

		private void ExecuteFeedSmelter()
		{
			float value = Plugin.KilnDistance.Value;
			if (IsCloseEnough(_targetObj, value, value))
			{
				Smelter component = _targetObj.GetComponent<Smelter>();
				if (!((Object)(object)component != (Object)null) || _heldItemData == null)
				{
					return;
				}
				ZNetView component2 = ((Component)component).GetComponent<ZNetView>();
				bool flag = (Object)(object)component.m_fuelItem != (Object)null && component.m_fuelItem.m_itemData.m_shared.m_name == _heldItemData.m_shared.m_name;
				string text = (((Object)(object)_heldItemData.m_dropPrefab != (Object)null) ? ((Object)_heldItemData.m_dropPrefab).name : _heldItemData.m_shared.m_name);
				Logger.LogWarning((object)$"[AssistantAI] ExecuteFeedSmelter. isFuel={flag}, prefabName={text}, IsOwner={component2.IsOwner()}");
				if (flag)
				{
					float num = component2.GetZDO().GetFloat("fuel", 0f);
					int num2 = Mathf.FloorToInt((float)component.m_maxFuel - num);
					int num3 = Mathf.Min(num2, _heldItemData.m_stack);
					Logger.LogWarning((object)$"[AssistantAI] Feed FUEL: current={num}, space={num2}, amountToFeed={num3}");
					if (num3 > 0)
					{
						if (!component2.IsOwner())
						{
							component2.ClaimOwnership();
						}
						component2.GetZDO().Set("fuel", num + (float)num3);
						component2.InvokeRPC(ZNetView.Everybody, "AddFuelItem", Array.Empty<object>());
						ZSyncAnimation component3 = ((Component)this).GetComponent<ZSyncAnimation>();
						if ((Object)(object)component3 != (Object)null)
						{
							component3.SetTrigger("interact");
						}
						ItemData heldItemData = _heldItemData;
						heldItemData.m_stack -= num3;
						if (_heldItemData.m_stack <= 0)
						{
							_heldItemData = null;
							SetTask("Idle", null);
						}
						return;
					}
				}
				else
				{
					int num4 = component2.GetZDO().GetInt("queued", 0);
					int num5 = component.m_maxOre - num4;
					int num6 = Mathf.Min(num5, _heldItemData.m_stack);
					bool flag2 = false;
					if (component.m_conversion != null)
					{
						foreach (ItemConversion item in component.m_conversion)
						{
							if ((Object)(object)item.m_from != (Object)null && ((Object)((Component)item.m_from).gameObject).name == text)
							{
								flag2 = true;
								break;
							}
						}
					}
					Logger.LogWarning((object)$"[AssistantAI] Feed ORE: queued={num4}, space={num5}, amountToFeed={num6}, isAllowed={flag2}");
					if (num6 > 0)
					{
						if (!flag2)
						{
							Logger.LogWarning((object)("[AssistantAI] ERROR: Smelter " + ((Object)component).name + " DOES NOT ALLOW item " + text + "!"));
							DropHoldingItem();
							SetTask("Idle", null);
							return;
						}
						if (!component2.IsOwner())
						{
							component2.ClaimOwnership();
						}
						for (int i = 0; i < num6; i++)
						{
							component2.GetZDO().Set("item" + (num4 + i), text);
						}
						component2.GetZDO().Set("queued", num4 + num6);
						component2.InvokeRPC(ZNetView.Everybody, "AddOreItem", Array.Empty<object>());
						ZSyncAnimation component4 = ((Component)this).GetComponent<ZSyncAnimation>();
						if ((Object)(object)component4 != (Object)null)
						{
							component4.SetTrigger("interact");
						}
						int num7 = component2.GetZDO().GetInt("queued", 0);
						Logger.LogWarning((object)$"[AssistantAI] Queued BEFORE: {num4}, AFTER ZDO: {num7}");
						ItemData heldItemData2 = _heldItemData;
						heldItemData2.m_stack -= num6;
						if (_heldItemData.m_stack <= 0)
						{
							_heldItemData = null;
							SetTask("Idle", null);
						}
						return;
					}
				}
				SetTask("Idle", null);
			}
			else
			{
				_monsterAI.SetFollowTarget(_targetObj);
			}
		}

		private bool IsUnderAttack()
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			if (_character.GetHealth() < _character.GetMaxHealth())
			{
				return true;
			}
			if ((Object)(object)RandEventSystem.instance != (Object)null && RandEventSystem.instance.GetCurrentRandomEvent() != null)
			{
				RandomEvent currentRandomEvent = RandEventSystem.instance.GetCurrentRandomEvent();
				if (Vector3.Distance(((Component)this).transform.position, currentRandomEvent.m_pos) <= 100f)
				{
					return true;
				}
			}
			return false;
		}

		private Container FindInboxChestWithValidItems()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			List<Piece> list = new List<Piece>();
			Piece.GetAllPiecesInRadius(((Component)this).transform.position, Plugin.WorkRadius.Value, list);
			foreach (Piece item in list)
			{
				if (!((Object)item).name.StartsWith("AssistantInboxChest") && !item.m_name.Contains("Caixa de Entrada"))
				{
					continue;
				}
				Container component = ((Component)item).GetComponent<Container>();
				if (!((Object)(object)component != (Object)null) || component.GetInventory().GetAllItems().Count <= 0)
				{
					continue;
				}
				foreach (ItemData allItem in component.GetInventory().GetAllItems())
				{
					if (allItem.m_shared.m_maxStackSize > 1 && HasDestinationChestForItem(allItem.m_shared.m_name))
					{
						return component;
					}
				}
			}
			return null;
		}

		private bool HasDestinationChestForItem(string localizedName)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			if (string.IsNullOrEmpty(localizedName))
			{
				return false;
			}
			List<Piece> list = new List<Piece>();
			Piece.GetAllPiecesInRadius(((Component)this).transform.position, Plugin.WorkRadius.Value, list);
			foreach (Piece item in list)
			{
				if (((Object)item).name.StartsWith("AssistantInboxChest") || item.m_name.Contains("Caixa de Entrada") || ((Object)item).name.Contains("personal"))
				{
					continue;
				}
				Container component = ((Component)item).GetComponent<Container>();
				if (!((Object)(object)component != (Object)null) || component.GetInventory() == null)
				{
					continue;
				}
				Inventory inventory = component.GetInventory();
				if (!inventory.HaveItem(localizedName, true))
				{
					continue;
				}
				bool flag = false;
				foreach (ItemData allItem in inventory.GetAllItems())
				{
					if (allItem.m_shared.m_name == localizedName && allItem.m_stack < allItem.m_shared.m_maxStackSize)
					{
						flag = true;
						break;
					}
				}
				if (!flag && inventory.GetEmptySlots() > 0)
				{
					flag = true;
				}
				if (flag)
				{
					return true;
				}
			}
			return false;
		}

		private void ExecuteTakeFromInbox()
		{
			float value = Plugin.ChestDistance.Value;
			if (IsCloseEnough(_targetObj, value, value))
			{
				Container component = _targetObj.GetComponent<Container>();
				if ((Object)(object)component != (Object)null && component.GetInventory() != null)
				{
					foreach (ItemData allItem in component.GetInventory().GetAllItems())
					{
						if (allItem.m_shared.m_maxStackSize <= 1 || !HasDestinationChestForItem(allItem.m_shared.m_name))
						{
							continue;
						}
						int num = Mathf.Min(allItem.m_stack, allItem.m_shared.m_maxStackSize);
						if (!((Object)(object)allItem.m_dropPrefab == (Object)null))
						{
							_heldItemData = allItem.Clone();
							_heldItemData.m_stack = num;
							((Component)component).GetComponent<ZNetView>().ClaimOwnership();
							component.GetInventory().RemoveItem(allItem, num);
							ZSyncAnimation component2 = ((Component)this).GetComponent<ZSyncAnimation>();
							if ((Object)(object)component2 != (Object)null)
							{
								component2.SetTrigger("interact");
							}
							component.SetInUse(true);
							((MonoBehaviour)this).StartCoroutine(CloseChest(component));
							ZSFX componentInChildren = _targetObj.GetComponentInChildren<ZSFX>();
							if ((Object)(object)componentInChildren != (Object)null)
							{
								componentInChildren.Play();
							}
							break;
						}
					}
				}
				SetTask("Idle", null);
				FindNewTask();
			}
			else
			{
				_monsterAI.SetFollowTarget(_targetObj);
			}
		}
	}
	public class AssistantBedMarker : MonoBehaviour, Interactable, Hoverable
	{
		private GameObject _marker;

		private bool _showMarker;

		private void Start()
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			GameObject prefab = Cache.GetPrefab<GameObject>("piece_workbench");
			if (!((Object)(object)prefab != (Object)null))
			{
				return;
			}
			CraftingStation component = prefab.GetComponent<CraftingStation>();
			if ((Object)(object)component != (Object)null && (Object)(object)component.m_areaMarker != (Object)null)
			{
				_marker = Object.Instantiate<GameObject>(component.m_areaMarker, ((Component)this).transform.position, Quaternion.identity, ((Component)this).transform);
				_marker.SetActive(false);
				float value = Plugin.WorkRadius.Value;
				CircleProjector componentInChildren = _marker.GetComponentInChildren<CircleProjector>();
				if ((Object)(object)componentInChildren != (Object)null)
				{
					componentInChildren.m_radius = value;
					componentInChildren.m_nrOfSegments = Mathf.Max(32, (int)(value * 4f));
				}
			}
		}

		public bool Interact(Humanoid user, bool hold, bool alt)
		{
			if (hold)
			{
				return false;
			}
			_showMarker = !_showMarker;
			if ((Object)(object)_marker != (Object)null)
			{
				_marker.SetActive(_showMarker);
			}
			((Character)user).Message((MessageType)2, _showMarker ? $"Área do Assistente Visível ({Plugin.WorkRadius.Value}m)" : "Área do Assistente Oculta", 0, (Sprite)null);
			return true;
		}

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

		public string GetHoverText()
		{
			return "\n[<color=yellow><b>E</b></color>] " + (_showMarker ? "Ocultar Área de Trabalho" : "Mostrar Área de Trabalho");
		}

		public string GetHoverName()
		{
			return "Cama do Assistente";
		}
	}
	public class AssistantSpawner : MonoBehaviour
	{
		private ZNetView _nview;

		private GameObject _spawnedNPC;

		private const string ZDO_NPC_ID = "AssistantNPC_ID";

		private ZDOID _cachedNpcId = ZDOID.None;

		private void Awake()
		{
			_nview = ((Component)this).GetComponent<ZNetView>();
			((MonoBehaviour)this).Invoke("TrySpawnNPC", 1f);
		}

		private void TrySpawnNPC()
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: 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_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: 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_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: 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_009c: 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_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_nview == (Object)null || !_nview.IsOwner())
			{
				return;
			}
			ZDOID val = (_cachedNpcId = _nview.GetZDO().GetZDOID("AssistantNPC_ID"));
			if (val == ZDOID.None)
			{
				GameObject prefab = Cache.GetPrefab<GameObject>("BaseAssistantNPC");
				if ((Object)(object)prefab != (Object)null)
				{
					Vector3 val2 = ((Component)this).transform.position + ((Component)this).transform.forward * 1.5f + Vector3.up * 1f;
					_spawnedNPC = Object.Instantiate<GameObject>(prefab, val2, ((Component)this).transform.rotation);
					ZNetView component = _spawnedNPC.GetComponent<ZNetView>();
					if ((Object)(object)component != (Object)null)
					{
						_cachedNpcId = component.GetZDO().m_uid;
						_nview.GetZDO().Set("AssistantNPC_ID", _cachedNpcId);
						component.GetZDO().Set("HomeBedPos", ((Component)this).transform.position);
					}
				}
			}
			else
			{
				ZDO zDO = ZDOMan.instance.GetZDO(val);
				if (zDO != null)
				{
					zDO.Set("HomeBedPos", ((Component)this).transform.position);
				}
			}
		}

		private void OnDestroy()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: 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_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_nview == (Object)null || !_nview.IsOwner() || !(_cachedNpcId != ZDOID.None))
			{
				return;
			}
			GameObject val = ZNetScene.instance.FindInstance(_cachedNpcId);
			if ((Object)(object)val != (Object)null)
			{
				ZNetView component = val.GetComponent<ZNetView>();
				if ((Object)(object)component != (Object)null)
				{
					component.ClaimOwnership();
					GameObject prefab = Cache.GetPrefab<GameObject>("vfx_corpse_destruction");
					if ((Object)(object)prefab != (Object)null)
					{
						Object.Instantiate<GameObject>(prefab, val.transform.position, Quaternion.identity);
					}
					component.Destroy();
				}
			}
			else
			{
				ZDO zDO = ZDOMan.instance.GetZDO(_cachedNpcId);
				if (zDO != null)
				{
					ZDOMan.instance.DestroyZDO(zDO);
				}
			}
		}
	}
	[HarmonyPatch(typeof(Player), "PlacePiece")]
	public static class Player_PlacePiece_Patch
	{
		public static bool Prefix(Player __instance, Piece piece)
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)piece != (Object)null && ((Object)((Component)piece).gameObject).name.Contains("AssistantTotem"))
			{
				int num = 0;
				AssistantSpawner[] array = Object.FindObjectsOfType<AssistantSpawner>();
				foreach (AssistantSpawner assistantSpawner in array)
				{
					ZNetView component = ((Component)assistantSpawner).GetComponent<ZNetView>();
					if (!((Object)(object)component == (Object)null) && component.GetZDO() != null && Vector3.Distance(((Component)__instance).transform.position, ((Component)assistantSpawner).transform.position) < Plugin.WorkRadius.Value)
					{
						num++;
					}
				}
				if (num >= 3)
				{
					((Character)__instance).Message((MessageType)2, "Limite de 3 Assistentes por base atingido!", 0, (Sprite)null);
					return false;
				}
			}
			return true;
		}
	}
	public class AssistantChestTextReceiver : MonoBehaviour, TextReceiver
	{
		public string GetText()
		{
			ZNetView component = ((Component)this).GetComponent<ZNetView>();
			if ((Object)(object)component == (Object)null || !component.IsValid())
			{
				return "";
			}
			return component.GetZDO().GetString("text", "");
		}

		public void SetText(string text)
		{
			ZNetView component = ((Component)this).GetComponent<ZNetView>();
			if ((Object)(object)component != (Object)null && component.IsValid())
			{
				component.ClaimOwnership();
				component.GetZDO().Set("text", text);
			}
		}
	}
	[HarmonyPatch(typeof(Container))]
	public static class ContainerPatches
	{
		private static void EnsureTextReceiver(Container container)
		{
			if ((Object)(object)((Component)container).GetComponent<AssistantChestTextReceiver>() == (Object)null)
			{
				((Component)container).gameObject.AddComponent<AssistantChestTextReceiver>();
			}
		}

		[HarmonyPatch("Interact")]
		[HarmonyPrefix]
		public static bool Interact_Prefix(Container __instance, Humanoid character, bool hold, bool alt)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			EnsureTextReceiver(__instance);
			if (hold)
			{
				return true;
			}
			if (alt)
			{
				if (!PrivateArea.CheckAccess(((Component)__instance).transform.position, 0f, true, false))
				{
					return false;
				}
				TextInput.instance.RequestText((TextReceiver)(object)((Component)__instance).GetComponent<AssistantChestTextReceiver>(), "Configuração do Assistente", 20);
				return false;
			}
			return true;
		}

		[HarmonyPatch("GetHoverText")]
		[HarmonyPostfix]
		public static void GetHoverText_Postfix(Container __instance, ref string __result)
		{
			EnsureTextReceiver(__instance);
			ZNetView component = ((Component)__instance).GetComponent<ZNetView>();
			if ((Object)(object)component != (Object)null && component.IsValid())
			{
				string text = component.GetZDO().GetString("text", "");
				if (!string.IsNullOrEmpty(text))
				{
					__result = "[<color=yellow>" + text + "</color>]\n" + __result;
				}
				__result += "\n[<color=yellow><b>L-Shift + E</b></color>] Renomear (Assistente)";
			}
		}
	}
	[BepInPlugin("com.singularitydot.baseassistant", "Base Assistant", "0.1.3")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		public const string PluginGUID = "com.singularitydot.baseassistant";

		public const string PluginName = "Base Assistant";

		public const string PluginVersion = "0.1.3";

		public static ConfigEntry<float> WorkRadius;

		public static ConfigEntry<float> RepairDistance;

		public static ConfigEntry<float> ChestDistance;

		public static ConfigEntry<float> KilnDistance;

		public static ConfigEntry<float> GroundItemDistance;

		public static ConfigEntry<float> StuckTimeout;

		public static ConfigEntry<float> TaskTimeout;

		public static ConfigEntry<float> NpcWalkSpeed;

		public static ConfigEntry<float> NpcRunSpeed;

		public static ConfigEntry<float> RepairHealthThreshold;

		public static ConfigEntry<float> AoERepairRadius;

		public static ConfigEntry<int> MaxCoalAmount;

		public static ConfigEntry<int> MaxSmeltedMetal;

		public static ConfigEntry<int> LeaveWoodAmount;

		public static ConfigEntry<int> LeaveCoalAmount;

		public static ConfigEntry<int> LeaveOreAmount;

		public static ConfigEntry<bool> EnableRepairing;

		public static ConfigEntry<bool> EnableSmelting;

		public static ConfigEntry<bool> EnableLooting;

		public static ConfigEntry<bool> EnableSorting;

		public static ConfigEntry<bool> EnableAutoLabeling;

		public static ConfigEntry<string> TagWeapons;

		public static ConfigEntry<string> TagArmor;

		public static ConfigEntry<string> TagFood;

		public static ConfigEntry<string> TagWood;

		public static ConfigEntry<string> TagMetal;

		public static ConfigEntry<string> TagIgnore;

		private readonly Harmony harmony = new Harmony("com.singularitydot.baseassistant");

		private float _configReloadTimer;

		private void Awake()
		{
			harmony.PatchAll();
			EnableRepairing = ((BaseUnityPlugin)this).Config.Bind<bool>("1. Geral", "AtivarReparos", true, "Permite que o assistente repare estruturas danificadas.");
			EnableSmelting = ((BaseUnityPlugin)this).Config.Bind<bool>("1. Geral", "AtivarFornalhas", true, "Permite que o assistente abasteça fornalhas e fundições.");
			EnableLooting = ((BaseUnityPlugin)this).Config.Bind<bool>("1. Geral", "AtivarColetaDeChao", true, "Permite que o assistente pegue itens soltos no chão.");
			EnableSorting = ((BaseUnityPlugin)this).Config.Bind<bool>("1. Geral", "AtivarOrganizacao", true, "Permite que o assistente organize itens do baú mestre para os outros baús.");
			EnableAutoLabeling = ((BaseUnityPlugin)this).Config.Bind<bool>("1. Geral", "AtivarAutoRotulagem", true, "Permite que o assistente renomeie baús vazios automaticamente ao guardar itens.");
			WorkRadius = ((BaseUnityPlugin)this).Config.Bind<float>("1. Geral", "RaioDeTrabalho", 30f, "Raio de ação do assistente a partir do Totem.");
			RepairHealthThreshold = ((BaseUnityPlugin)this).Config.Bind<float>("1. Geral", "VidaParaReparo", 0.8f, "Porcentagem de vida (0.0 a 1.0) para que o assistente decida consertar uma estrutura.");
			AoERepairRadius = ((BaseUnityPlugin)this).Config.Bind<float>("1. Geral", "RaioReparoEmArea", 10f, "Raio (em metros) em volta da peça que ele vai consertar tudo de uma vez com o poder da telepatia.");
			NpcWalkSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("1. Geral", "VelocidadeAndar", 3f, "Velocidade do NPC quando está andando.");
			NpcRunSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("1. Geral", "VelocidadeCorrer", 6f, "Velocidade do NPC quando está correndo para concluir uma tarefa.");
			TagWeapons = ((BaseUnityPlugin)this).Config.Bind<string>("5. Regras de Baus", "TagArmas", "armas, weapons, arsenal", "Palavras-chave (separadas por vírgula) que o assistente reconhecerá no nome do baú para guardar Armas e Ferramentas.");
			TagArmor = ((BaseUnityPlugin)this).Config.Bind<string>("5. Regras de Baus", "TagArmadura", "armaduras, armor, equipamentos", "Palavras-chave que o assistente reconhecerá para guardar Armaduras e Escudos.");
			TagFood = ((BaseUnityPlugin)this).Config.Bind<string>("5. Regras de Baus", "TagComida", "comida, food, rango, consumiveis", "Palavras-chave que o assistente reconhecerá para guardar Comidas e Poções.");
			TagWood = ((BaseUnityPlugin)this).Config.Bind<string>("5. Regras de Baus", "TagMadeira", "wood, lenha", "Palavras-chave que o assistente reconhecerá para guardar Madeiras em geral.");
			TagMetal = ((BaseUnityPlugin)this).Config.Bind<string>("5. Regras de Baus", "TagMetal", "metal, minério, ore", "Palavras-chave que o assistente reconhecerá para guardar Minérios e Metais fundidos.");
			TagIgnore = ((BaseUnityPlugin)this).Config.Bind<string>("5. Regras de Baus", "TagIgnorar", "ignorar, privado, nao tocar, ignore", "Palavras-chave que o assistente reconhecerá para IGNORAR completamente o baú.");
			string text = "\n[AVISO] Alterar as distâncias de interação pode deixar o visual do jogo estranho e algumas vezes macabro (telecinese e itens flutuando).\n[Warning] Changing interaction distances may cause weird or macabre visual behaviors (telekinesis and floating items).";
			RepairDistance = ((BaseUnityPlugin)this).Config.Bind<float>("2. Distancias", "DistanciaParaConserto", 6f, "Distância máxima para ele consertar paredes, pisos e fornalhas." + text);
			KilnDistance = ((BaseUnityPlugin)this).Config.Bind<float>("2. Distancias", "DistanciaFornalha", 4f, "Distância máxima para abastecer fornalhas." + text);
			ChestDistance = ((BaseUnityPlugin)this).Config.Bind<float>("2. Distancias", "DistanciaBau", 2.5f, "Distância máxima para guardar ou pegar itens no baú." + text);
			GroundItemDistance = ((BaseUnityPlugin)this).Config.Bind<float>("2. Distancias", "DistanciaItemChao", 2f, "Distância máxima para pegar itens que estão no chão." + text);
			StuckTimeout = ((BaseUnityPlugin)this).Config.Bind<float>("3. Desatolamento", "TempoAteTeleportar", 5f, "Tempo (em segundos) que ele precisa ficar travado para ativar o teleporte.");
			TaskTimeout = ((BaseUnityPlugin)this).Config.Bind<float>("3. Desatolamento", "TempoMaximoTarefa", 60f, "Tempo máximo (em segundos) que ele fica tentando concluir uma tarefa antes de desistir e resetar.");
			MaxCoalAmount = ((BaseUnityPlugin)this).Config.Bind<int>("4. Producao", "MaximoCarvao", 200, "Quantidade máxima de carvão nos baús antes do Assistente parar de abastecer a Fornalha de Carvão.");
			MaxSmeltedMetal = ((BaseUnityPlugin)this).Config.Bind<int>("4. Producao", "MaximoMetal", 100, "Quantidade máxima de um metal nos baús antes do Assistente parar de colocar minério na Fundição.");
			LeaveWoodAmount = ((BaseUnityPlugin)this).Config.Bind<int>("4. Producao", "ReservaMadeira", 10, "Quantidade mínima de segurança de madeira que ele nunca vai retirar do baú.");
			LeaveCoalAmount = ((BaseUnityPlugin)this).Config.Bind<int>("4. Producao", "ReservaCarvao", 10, "Quantidade mínima de segurança de carvão que ele nunca vai retirar do baú para fornalhas.");
			LeaveOreAmount = ((BaseUnityPlugin)this).Config.Bind<int>("4. Producao", "ReservaMinerio", 0, "Quantidade mínima de segurança de minério cru que ele deixará intocado no baú.");
			((BaseUnityPlugin)this).Logger.LogInfo((object)"O mod Base Assistant (v0.1.3) foi carregado com sucesso!");
			PrefabManager.OnVanillaPrefabsAvailable += RegisterPieces;
			PrefabManager.OnVanillaPrefabsAvailable += ModifyClonedPrefabs;
			PrefabManager.OnVanillaPrefabsAvailable += CreateAssistantPrefab;
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new ClearChestsCommand());
		}

		private void RegisterPieces()
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			//IL_0050: 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_0060: 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_0070: Expected O, but got Unknown
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Expected O, but got Unknown
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Expected O, but got Unknown
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Expected O, but got Unknown
			//IL_00ee: 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_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Expected O, but got Unknown
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Expected O, but got Unknown
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Expected O, but got Unknown
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Expected O, but got Unknown
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ac: Expected O, but got Unknown
			//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cd: Expected O, but got Unknown
			//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01df: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ee: Expected O, but got Unknown
			//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0200: Unknown result type (might be due to invalid IL or missing references)
			//IL_0207: Unknown result type (might be due to invalid IL or missing references)
			//IL_020f: Expected O, but got Unknown
			//IL_0226: Unknown result type (might be due to invalid IL or missing references)
			//IL_0230: Expected O, but got Unknown
			PieceManager.Instance.AddPieceCategory("Hammer", "Base Assistant");
			PieceConfig val = new PieceConfig();
			val.Name = "Caixa de Entrada (Assistente)";
			val.Description = "Baú Mestre: Coloque seus itens aqui para o Assistente organizar automaticamente nos outros baús da base.";
			val.PieceTable = "Hammer";
			val.Category = "Base Assistant";
			val.Requirements = (RequirementConfig[])(object)new RequirementConfig[2]
			{
				new RequirementConfig
				{
					Item = "Wood",
					Amount = 10,
					Recover = true
				},
				new RequirementConfig
				{
					Item = "Resin",
					Amount = 2,
					Recover = true
				}
			};
			PieceConfig val2 = val;
			PieceManager.Instance.AddPiece(new CustomPiece("AssistantInboxChest", "piece_chest_wood", val2));
			val = new PieceConfig();
			val.Name = "Totem do Assistente";
			val.Description = "Invoque o Assistente Dverger! O totem define o centro da área de trabalho do seu assistente.";
			val.PieceTable = "Hammer";
			val.Category = "Base Assistant";
			val.Requirements = (RequirementConfig[])(object)new RequirementConfig[2]
			{
				new RequirementConfig
				{
					Item = "Wood",
					Amount = 10,
					Recover = true
				},
				new RequirementConfig
				{
					Item = "GreydwarfEye",
					Amount = 1,
					Recover = true
				}
			};
			PieceConfig val3 = val;
			PieceManager.Instance.AddPiece(new CustomPiece("AssistantTotem", "guard_stone", val3));
			val = new PieceConfig();
			val.Name = "Cama do Assistente";
			val.Description = "Construa esta cama para que o seu Assistente tenha onde dormir à noite.";
			val.PieceTable = "Hammer";
			val.Category = "Base Assistant";
			val.Requirements = (RequirementConfig[])(object)new RequirementConfig[4]
			{
				new RequirementConfig
				{
					Item = "Wood",
					Amount = 10,
					Recover = true
				},
				new RequirementConfig
				{
					Item = "DeerHide",
					Amount = 4,
					Recover = true
				},
				new RequirementConfig
				{
					Item = "LeatherScraps",
					Amount = 4,
					Recover = true
				},
				new RequirementConfig
				{
					Item = "BronzeNails",
					Amount = 5,
					Recover = true
				}
			};
			PieceConfig val4 = val;
			PieceManager.Instance.AddPiece(new CustomPiece("BaseAssistantBed", "bed", val4));
		}

		private void ModifyClonedPrefabs()
		{
			GameObject prefab = Cache.GetPrefab<GameObject>("AssistantTotem");
			if ((Object)(object)prefab != (Object)null)
			{
				PrivateArea component = prefab.GetComponent<PrivateArea>();
				if ((Object)(object)component != (Object)null)
				{
					Object.DestroyImmediate((Object)(object)component, true);
				}
				CircleProjector[] componentsInChildren = prefab.GetComponentsInChildren<CircleProjector>(true);
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					Object.DestroyImmediate((Object)(object)((Component)componentsInChildren[i]).gameObject, true);
				}
				prefab.AddComponent<AssistantBedMarker>();
				prefab.AddComponent<AssistantSpawner>();
			}
			GameObject prefab2 = Cache.GetPrefab<GameObject>("BaseAssistantBed");
			if ((Object)(object)prefab2 != (Object)null)
			{
				Bed component2 = prefab2.GetComponent<Bed>();
				if ((Object)(object)component2 != (Object)null)
				{
					Object.DestroyImmediate((Object)(object)component2, true);
				}
			}
			PrefabManager.OnVanillaPrefabsAvailable -= ModifyClonedPrefabs;
		}

		private void Update()
		{
			_configReloadTimer += Time.deltaTime;
			if (_configReloadTimer >= 5f)
			{
				_configReloadTimer = 0f;
				((BaseUnityPlugin)this).Config.Reload();
			}
		}

		private void CreateAssistantPrefab()
		{
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Expected O, but got Unknown
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Expected O, but got Unknown
			GameObject prefab = Cache.GetPrefab<GameObject>("Dverger");
			if ((Object)(object)prefab == (Object)null)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)"Não foi possível encontrar o modelo do Dverger!");
				return;
			}
			GameObject obj = PrefabManager.Instance.CreateClonedPrefab("BaseAssistantNPC", prefab);
			Character component = obj.GetComponent<Character>();
			if ((Object)(object)component != (Object)null)
			{
				component.m_name = "Assistente da Base";
			}
			CharacterDrop component2 = obj.GetComponent<CharacterDrop>();
			if ((Object)(object)component2 != (Object)null)
			{
				Object.Destroy((Object)(object)component2);
			}
			MonsterAI component3 = obj.GetComponent<MonsterAI>();
			if ((Object)(object)component3 != (Object)null)
			{
				((BaseAI)component3).m_idleSound = new EffectList();
			}
			obj.AddComponent<AssistantAI>();
			CustomCreature val = new CustomCreature(obj, true);
			CreatureManager.Instance.AddCreature(val);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Assistente Base gerada com sucesso!");
			PrefabManager.OnVanillaPrefabsAvailable -= CreateAssistantPrefab;
		}
	}
	public class ClearChestsCommand : ConsoleCommand
	{
		public override string Name => "limparbaus";

		public override string Help => "Apaga o texto (rótulo) de todos os baús na área carregada (Comando do BaseAssistant).";

		public override void Run(string[] args)
		{
			if ((Object)(object)Player.m_localPlayer == (Object)null)
			{
				Logger.LogWarning((object)"Você precisa estar no jogo com um personagem para usar este comando.");
				return;
			}
			int num = 0;
			Container[] array = Object.FindObjectsOfType<Container>();
			for (int i = 0; i < array.Length; i++)
			{
				ZNetView component = ((Component)array[i]).GetComponent<ZNetView>();
				if ((Object)(object)component != (Object)null && component.IsValid() && !string.IsNullOrEmpty(component.GetZDO().GetString("text", "")))
				{
					component.ClaimOwnership();
					component.GetZDO().Set("text", "");
					num++;
				}
			}
			string text = $"[BaseAssistant] {num} baús tiveram seus rótulos apagados com sucesso.";
			Logger.LogInfo((object)text);
			if ((Object)(object)Console.instance != (Object)null)
			{
				Console.instance.Print(text);
			}
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "BaseAssistant";

		public const string PLUGIN_NAME = "BaseAssistant";

		public const string PLUGIN_VERSION = "1.0.0";
	}
}