Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of Hearthfolk v1.3.1
BepInEx/plugins/Hearthfolk/Hearthfolk.dll
Decompiled 2 weeks ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Hearthfolk.Jobs; using Jotunn; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using Jotunn.Utils; using Microsoft.CodeAnalysis; using Splatform; using UnityEngine; using UnityEngine.Rendering; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: IgnoresAccessChecksTo("assembly_guiutils")] [assembly: IgnoresAccessChecksTo("assembly_valheim")] [assembly: AssemblyCompany("Hearthfolk")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.3.1.0")] [assembly: AssemblyInformationalVersion("1.3.1+6157fd8a14c5e6158e0c890a1d18812d77a5f0ed")] [assembly: AssemblyProduct("Hearthfolk")] [assembly: AssemblyTitle("Hearthfolk")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.3.1.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 Hearthfolk { [HarmonyPatch(typeof(WearNTear), "ApplyDamage")] internal static class BaseDamageDefensePatch { [HarmonyPostfix] private static void Postfix(WearNTear __instance, float damage, HitData hitData, bool __result) { if (__result && !(damage <= 0f) && hitData != null) { ExilesHearth.ReportBaseDamage(__instance, hitData.GetAttacker()); } } } [HarmonyPatch(typeof(Chair), "Interact")] internal static class ChairInteractPatch { private static bool Prefix(Chair __instance, Humanoid human, bool hold, ref bool __result) { if (hold || !SettlerController.IsSeatReserved(__instance)) { return true; } Player val = (Player)(object)((human is Player) ? human : null); if (val != null && (Object)(object)val == (Object)(object)Player.m_localPlayer) { ((Character)val).Message((MessageType)2, "$msg_blocked", 0, (Sprite)null, false); } __result = false; return false; } } internal sealed class ChestSortPanel : MonoBehaviour { private sealed class ItemChoice { internal string SharedName; internal string DisplayName; internal Sprite Icon; } private const float PanelWidth = 620f; private const float PanelHeight = 690f; private const float MaxUseDistance = 10f; private static ChestSortPanel _instance; private Container _container; private Rect _rect; private float _layoutScale = 1f; private Vector2 _scroll; private string _search = string.Empty; private bool _wasConfigured; private HashSet<string> _selected = new HashSet<string>(StringComparer.Ordinal); private List<ItemChoice> _choices = new List<ItemChoice>(); internal static void Toggle(Container container) { if ((Object)(object)_instance == (Object)null) { GameObject val = (((Object)(object)HearthfolkPlugin.Instance != (Object)null) ? ((Component)HearthfolkPlugin.Instance).gameObject : null); if ((Object)(object)val == (Object)null) { return; } _instance = val.AddComponent<ChestSortPanel>(); } if ((Object)(object)_instance._container == (Object)(object)container) { _instance.Close(); } else { _instance.Open(container); } } private void Open(Container container) { //IL_005b: 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) Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null) && ChestSortRules.CanConfigure(container, localPlayer.GetPlayerID())) { _container = container; _wasConfigured = ChestSortRules.IsConfigured(container); _selected = ChestSortRules.ReadItems(container); _choices = BuildChoices(container, _selected); _search = string.Empty; _scroll = Vector2.zero; LayoutWindow(); GUIManager.BlockInput(true); } } private void LayoutWindow() { //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) _layoutScale = HfGuiSkin.Scale; float num = Mathf.Min(620f, Mathf.Max(320f, HfGuiSkin.ViewWidth - 40f)); float num2 = Mathf.Min(690f, Mathf.Max(320f, HfGuiSkin.ViewHeight - 40f)); _rect = new Rect((HfGuiSkin.ViewWidth - num) / 2f, (HfGuiSkin.ViewHeight - num2) / 2f, num, num2); } private void Close() { _container = null; GUIManager.BlockInput(false); } private void OnDestroy() { if ((Object)(object)_container != (Object)null) { GUIManager.BlockInput(false); } } private void Update() { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_container == (Object)null)) { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || (Object)(object)_container == (Object)null || !((Component)_container).gameObject.activeInHierarchy || Vector3.Distance(((Component)localPlayer).transform.position, ((Component)_container).transform.position) > 10f || Input.GetKeyDown((KeyCode)27)) { Close(); return; } Cursor.lockState = (CursorLockMode)0; Cursor.visible = true; } } private void OnGUI() { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Expected O, but got Unknown //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_container == (Object)null)) { if (!Mathf.Approximately(_layoutScale, HfGuiSkin.Scale)) { LayoutWindow(); } GUISkin skin = GUI.skin; GUI.skin = HfGuiSkin.Get(); HfGuiSkin.BeginScaled(); _rect = GUILayout.Window(((Object)this).GetInstanceID(), _rect, new WindowFunction(DrawWindow), Localization.instance.Localize("$hf_chest_sort_title"), Array.Empty<GUILayoutOption>()); HfGuiSkin.EndScaled(); GUI.skin = skin; } } private void DrawWindow(int id) { //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_02f6: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_container == (Object)null) { return; } GUILayout.Space(4f); DrawIntakeStorageSection(); GUILayout.Space(8f); GUILayout.Label(Localization.instance.Localize(_wasConfigured ? "$hf_chest_sort_mode_explicit" : "$hf_chest_sort_mode_auto"), Array.Empty<GUILayoutOption>()); GUILayout.Label(Localization.instance.Localize("$hf_chest_sort_desc"), Array.Empty<GUILayoutOption>()); GUILayout.Space(5f); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.Label(Localization.instance.Localize("$hf_chest_sort_search"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(80f) }); _search = GUILayout.TextField(_search ?? string.Empty, Array.Empty<GUILayoutOption>()); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); if (GUILayout.Button(Localization.instance.Localize("$hf_chest_sort_select_present"), Array.Empty<GUILayoutOption>())) { SelectPresentMaterials(); } if (GUILayout.Button(Localization.instance.Localize("$hf_chest_sort_clear"), Array.Empty<GUILayoutOption>())) { _selected.Clear(); } GUILayout.EndHorizontal(); GUILayout.Space(5f); _scroll = GUILayout.BeginScrollView(_scroll, GUI.skin.box); List<ItemChoice> list = _choices.Where(MatchesSearch).ToList(); for (int i = 0; i < list.Count; i += 2) { GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); DrawChoice(list[i]); if (i + 1 < list.Count) { DrawChoice(list[i + 1]); } else { GUILayout.FlexibleSpace(); } GUILayout.EndHorizontal(); } if (list.Count == 0) { GUILayout.Label(Localization.instance.Localize("$hf_chest_sort_no_items"), Array.Empty<GUILayoutOption>()); } GUILayout.EndScrollView(); GUILayout.Space(6f); GUILayout.Label(string.Format(Localization.instance.Localize("$hf_chest_sort_selected"), _selected.Count), Array.Empty<GUILayoutOption>()); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); if (GUILayout.Button(Localization.instance.Localize("$hf_chest_sort_save"), Array.Empty<GUILayoutOption>())) { ChestSortRules.RequestSet(_container, _selected, configured: true); Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)2, "$hf_chest_sort_saved", 0, (Sprite)null, false); } Close(); } if (GUILayout.Button(Localization.instance.Localize("$hf_chest_sort_use_auto"), Array.Empty<GUILayoutOption>())) { ChestSortRules.RequestSet(_container, Array.Empty<string>(), configured: false); Player localPlayer2 = Player.m_localPlayer; if (localPlayer2 != null) { ((Character)localPlayer2).Message((MessageType)2, "$hf_chest_sort_auto_restored", 0, (Sprite)null, false); } Close(); } if (GUILayout.Button(Localization.instance.Localize("$hf_panel_close"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(90f) })) { Close(); } GUILayout.EndHorizontal(); GUI.DragWindow(new Rect(0f, 0f, 10000f, 20f)); } private void DrawIntakeStorageSection() { Player localPlayer = Player.m_localPlayer; long ownerId = (((Object)(object)localPlayer != (Object)null) ? localPlayer.GetPlayerID() : 0); ExilesHearth exilesHearth = ExilesHearth.IntakeCandidateFor(_container, ownerId); GUILayout.BeginVertical(GUI.skin.box, Array.Empty<GUILayoutOption>()); GUILayout.Label(Localization.instance.Localize("$hf_chest_intake_section"), HfGuiSkin.CardTitle, Array.Empty<GUILayoutOption>()); GUILayout.Label(Localization.instance.Localize("$hf_chest_intake_desc"), HfGuiSkin.MutedLabel, Array.Empty<GUILayoutOption>()); if ((Object)(object)exilesHearth == (Object)null) { GUILayout.Label(Localization.instance.Localize("$hf_chest_intake_no_hearth"), Array.Empty<GUILayoutOption>()); GUILayout.EndVertical(); return; } IntakeRoles intakeRoles = exilesHearth.IntakeRolesFor(_container); bool flag = intakeRoles != IntakeRoles.None; GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.Label(Localization.instance.Localize(flag ? "$hf_chest_intake_current" : "$hf_chest_intake_available"), Array.Empty<GUILayoutOption>()); GUILayout.FlexibleSpace(); if (GUILayout.Button(Localization.instance.Localize("$hf_chest_intake_all"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(120f) })) { exilesHearth.RequestSetIntakeStorageRoles(_container, IntakeRoles.All); if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)2, "$hf_chest_intake_saved", 0, (Sprite)null, false); } } if (flag && GUILayout.Button(Localization.instance.Localize("$hf_chest_intake_remove"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(120f) })) { exilesHearth.RequestSetIntakeStorageRoles(_container, IntakeRoles.None); } GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); DrawIntakeRoleToggle(exilesHearth, intakeRoles, IntakeRoles.Lumberjack, "$hf_role_lumberjack"); DrawIntakeRoleToggle(exilesHearth, intakeRoles, IntakeRoles.Miner, "$hf_role_miner"); DrawIntakeRoleToggle(exilesHearth, intakeRoles, IntakeRoles.Farmer, "$hf_role_farmer"); GUILayout.FlexibleSpace(); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); DrawIntakeRoleToggle(exilesHearth, intakeRoles, IntakeRoles.Forager, "$hf_role_forager"); DrawIntakeRoleToggle(exilesHearth, intakeRoles, IntakeRoles.Hunter, "$hf_role_hunter"); GUILayout.FlexibleSpace(); GUILayout.EndHorizontal(); GUILayout.EndVertical(); } private void DrawIntakeRoleToggle(ExilesHearth hearth, IntakeRoles roles, IntakeRoles role, string labelKey) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) bool flag = (roles & role) != 0; Color contentColor = GUI.contentColor; if (!flag) { GUI.contentColor = new Color(0.55f, 0.5f, 0.42f); } if (GUILayout.Button((flag ? "✓ " : "— ") + Localization.instance.Localize(labelKey), Array.Empty<GUILayoutOption>())) { hearth.RequestSetIntakeStorageRoles(_container, flag ? (roles & ~role) : (roles | role)); } GUI.contentColor = contentColor; } private void DrawChoice(ItemChoice choice) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: 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_001d: 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_0049: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: 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) //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Invalid comparison between Unknown and I4 //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) bool flag = _selected.Contains(choice.SharedName); Color backgroundColor = GUI.backgroundColor; Color contentColor = GUI.contentColor; if (flag) { GUI.backgroundColor = new Color(2.4f, 2f, 1.1f); GUI.contentColor = new Color(1f, 0.85f, 0.45f); } if (GUILayout.Button((flag ? "✓ " : string.Empty) + choice.DisplayName, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(275f), GUILayout.Height(42f) })) { if (flag) { _selected.Remove(choice.SharedName); } else { _selected.Add(choice.SharedName); } } Rect lastRect = GUILayoutUtility.GetLastRect(); if ((Object)(object)choice.Icon != (Object)null && (Object)(object)choice.Icon.texture != (Object)null && (int)Event.current.type == 7) { Rect textureRect = choice.Icon.textureRect; Texture2D texture = choice.Icon.texture; Rect val = default(Rect); ((Rect)(ref val))..ctor(((Rect)(ref textureRect)).x / (float)((Texture)texture).width, ((Rect)(ref textureRect)).y / (float)((Texture)texture).height, ((Rect)(ref textureRect)).width / (float)((Texture)texture).width, ((Rect)(ref textureRect)).height / (float)((Texture)texture).height); GUI.DrawTextureWithTexCoords(new Rect(((Rect)(ref lastRect)).x + 6f, ((Rect)(ref lastRect)).y + 5f, 32f, 32f), (Texture)(object)texture, val, true); } GUI.backgroundColor = backgroundColor; GUI.contentColor = contentColor; } private bool MatchesSearch(ItemChoice choice) { if (!string.IsNullOrWhiteSpace(_search) && choice.DisplayName.IndexOf(_search, StringComparison.OrdinalIgnoreCase) < 0) { return choice.SharedName.IndexOf(_search, StringComparison.OrdinalIgnoreCase) >= 0; } return true; } private void SelectPresentMaterials() { Container container = _container; Inventory val = ((container != null) ? container.GetInventory() : null); if (val == null) { return; } foreach (ItemData allItem in val.GetAllItems()) { if (ChestSortRules.IsSortable(allItem)) { _selected.Add(allItem.m_shared.m_name); } } } private static List<ItemChoice> BuildChoices(Container container, HashSet<string> selected) { HashSet<string> hashSet = new HashSet<string>(selected, StringComparer.Ordinal); Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)null) { hashSet.UnionWith(localPlayer.m_knownMaterial); } Inventory inventory = container.GetInventory(); if (inventory != null) { hashSet.UnionWith(from item in inventory.GetAllItems() where item != null select item.m_shared.m_name); } List<ItemChoice> list = new List<ItemChoice>(); if ((Object)(object)ObjectDB.instance == (Object)null) { return list; } foreach (GameObject item in ObjectDB.instance.m_items) { ItemData val = ((item != null) ? item.GetComponent<ItemDrop>() : null)?.m_itemData; if (ChestSortRules.IsSortable(val) && hashSet.Contains(val.m_shared.m_name)) { list.Add(new ItemChoice { SharedName = val.m_shared.m_name, DisplayName = Localization.instance.Localize(val.m_shared.m_name), Icon = val.GetIcon() }); } } return (from choice in list group choice by choice.SharedName into @group select @group.First() into choice orderby choice.DisplayName select choice).ToList(); } } internal static class ChestSortRules { private const char Separator = '|'; internal static void Register(Container container) { ZNetView val = container?.m_nview; if (!((Object)(object)val == (Object)null) && val.IsValid() && !(container is SettlerInventory)) { val.Register<long, string>("hf_SetChestSort", (Action<long, long, string>)delegate(long sender, long requesterId, string payload) { Receive(container, sender, requesterId, payload); }); } } internal static bool IsConfigured(Container container) { if (TryGetZdo(container, out var zdo)) { return zdo.GetBool("hf_sort_configured", false); } return false; } internal static HashSet<string> ReadItems(Container container) { HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal); if (!TryGetZdo(container, out var zdo)) { return hashSet; } string[] array = zdo.GetString("hf_sort_items", string.Empty).Split(new char[1] { '|' }, StringSplitOptions.RemoveEmptyEntries); foreach (string item in array) { hashSet.Add(item); } return hashSet; } internal static bool Accepts(Container container, string sharedName) { if ((Object)(object)container == (Object)null || string.IsNullOrEmpty(sharedName)) { return false; } if (IsConfigured(container)) { return ReadItems(container).Contains(sharedName); } Inventory inventory = container.GetInventory(); if (inventory != null) { return inventory.GetAllItems().Any((ItemData item) => item != null && item.m_shared.m_name == sharedName); } return false; } internal static bool IsSortable(ItemData item) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Invalid comparison between Unknown and I4 //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Invalid comparison between Unknown and I4 //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Invalid comparison between Unknown and I4 if (item == null || item.m_shared == null || item.m_shared.m_questItem) { return false; } ItemType itemType = item.m_shared.m_itemType; if (itemType - 1 <= 1 || (int)itemType == 13 || (int)itemType == 21) { return true; } return false; } internal static void RequestSet(Container container, IEnumerable<string> items, bool configured) { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null) && CanConfigure(container, localPlayer.GetPlayerID())) { string text = (configured ? ("1|" + string.Join('|'.ToString(), from name in items.Where((string name) => !string.IsNullOrEmpty(name) && name.IndexOf('|') < 0).Distinct() orderby name select name)) : "0"); if (!container.m_nview.IsOwner()) { container.m_nview.ClaimOwnership(); } container.m_nview.InvokeRPC("hf_SetChestSort", new object[2] { localPlayer.GetPlayerID(), text }); } } internal static bool IsStationaryPlayerChest(Container container) { if ((Object)(object)container == (Object)null || container is SettlerInventory || !((Component)container).gameObject.activeInHierarchy || (Object)(object)container.m_nview == (Object)null || !container.m_nview.IsValid() || (Object)(object)container.m_wagon != (Object)null || (Object)(object)((Component)container).GetComponentInParent<Ship>() != (Object)null || (Object)(object)((Component)container).GetComponentInParent<Vagon>() != (Object)null) { return false; } Piece val = ((Component)container).GetComponent<Piece>() ?? ((Component)container).GetComponentInParent<Piece>(); if ((Object)(object)val != (Object)null) { return val.IsPlacedByPlayer(); } return false; } internal static bool CanConfigure(Container container, long playerId) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) if (playerId != 0L && IsStationaryPlayerChest(container) && !ContainerInUse(container) && container.CheckAccess(playerId)) { return PrivateArea.CheckAccess(((Component)container).transform.position, 0f, false, false); } return false; } private static void Receive(Container container, long sender, long requesterId, string payload) { //IL_00c7: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)container == (Object)null || (Object)(object)container.m_nview == (Object)null || !container.m_nview.IsValid() || requesterId == 0L || !NetworkRequest.AuthenticatePlayer(sender, requesterId, "chest sorting change") || !IsStationaryPlayerChest(container) || !container.CheckAccess(requesterId) || string.IsNullOrEmpty(payload)) { return; } if (!container.m_nview.IsOwner()) { container.m_nview.ClaimOwnership(); if (!container.m_nview.IsOwner()) { return; } } bool flag = payload.StartsWith("1|", StringComparison.Ordinal); string text = ((flag && payload.Length > 2) ? payload.Substring(2) : string.Empty); ZDO zDO = container.m_nview.GetZDO(); zDO.Set("hf_sort_configured", flag); zDO.Set("hf_sort_items", text); Logger.LogInfo((object)($"Hearthfolk[sorting]: chest {zDO.m_uid} configured={flag} " + "items=[" + text + "] persisted")); } private static bool TryGetZdo(Container container, out ZDO zdo) { zdo = null; if ((Object)(object)container == (Object)null || (Object)(object)container.m_nview == (Object)null || !container.m_nview.IsValid()) { return false; } zdo = container.m_nview.GetZDO(); return zdo != null; } private static bool ContainerInUse(Container container) { if (!container.IsInUse()) { return container.m_nview.GetZDO().GetInt(ZDOVars.s_inUse, 0) == 1; } return true; } } internal sealed class ChopTarget { private readonly TreeBase _tree; private readonly TreeLog _log; private readonly Destructible _stump; private Collider _aimCollider; private bool _aimColliderResolved; internal bool IsLog => (Object)(object)_log != (Object)null; internal bool IsStump => (Object)(object)_stump != (Object)null; internal GameObject GameObject { get { if (!((Object)(object)_tree != (Object)null)) { if (!((Object)(object)_log != (Object)null)) { if (!((Object)(object)_stump != (Object)null)) { return null; } return ((Component)_stump).gameObject; } return ((Component)_log).gameObject; } return ((Component)_tree).gameObject; } } internal int InstanceId { get { if (!((Object)(object)GameObject != (Object)null)) { return 0; } return ((Object)GameObject).GetInstanceID(); } } internal Vector3 Center => GameObject.transform.position; internal int MinToolTier { get { if (!((Object)(object)_tree != (Object)null)) { if (!((Object)(object)_log != (Object)null)) { if (!((Object)(object)_stump != (Object)null)) { return 0; } return _stump.m_minToolTier; } return _log.m_minToolTier; } return _tree.m_minToolTier; } } internal ChopTarget(TreeBase tree) { _tree = tree; } internal ChopTarget(TreeLog log) { _log = log; } internal ChopTarget(Destructible stump) { _stump = stump; } internal bool IsValid() { GameObject gameObject = GameObject; if ((Object)(object)gameObject != (Object)null) { return gameObject.activeInHierarchy; } return false; } internal Vector3 ClosestPoint(Vector3 from) { //IL_0010: 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) //IL_0050: 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_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) GameObject gameObject = GameObject; if ((Object)(object)gameObject == (Object)null) { return from; } Collider val = ResolveAimCollider(gameObject); if ((Object)(object)val == (Object)null) { return gameObject.transform.position; } MeshCollider val2 = (MeshCollider)(object)((val is MeshCollider) ? val : null); if ((Object)(object)val2 != (Object)null && !val2.convex) { return val.ClosestPointOnBounds(from); } return val.ClosestPoint(from); } private Collider ResolveAimCollider(GameObject go) { //IL_005b: 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_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0072: 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) if (_aimColliderResolved && (Object)(object)_aimCollider != (Object)null) { return _aimCollider; } _aimColliderResolved = true; _aimCollider = null; float num = -1f; Collider[] componentsInChildren = go.GetComponentsInChildren<Collider>(false); foreach (Collider val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && !val.isTrigger && val.enabled) { Bounds bounds = val.bounds; Vector3 size = ((Bounds)(ref bounds)).size; float num2 = size.x * size.y * size.z; if (!(num2 <= num)) { _aimCollider = val; num = num2; } } } return _aimCollider; } internal float ReadHealth() { ZNetView val = (((Object)(object)_tree != (Object)null) ? _tree.m_nview : (((Object)(object)_log != (Object)null) ? _log.m_nview : (((Object)(object)_stump != (Object)null) ? _stump.m_nview : null))); float num = (((Object)(object)_tree != (Object)null) ? _tree.m_health : (((Object)(object)_log != (Object)null) ? _log.m_health : (((Object)(object)_stump != (Object)null) ? _stump.m_health : 0f))); if (!((Object)(object)val != (Object)null) || !val.IsValid()) { return num; } return val.GetZDO().GetFloat(ZDOVars.s_health, num); } internal void Damage(HitData hit) { if ((Object)(object)_tree != (Object)null) { _tree.Damage(hit); return; } if ((Object)(object)_log != (Object)null) { _log.Damage(hit); return; } Destructible stump = _stump; if (stump != null) { stump.Damage(hit); } } internal static bool IsTreeStump(Destructible destructible) { if ((Object)(object)destructible == (Object)null || (Object)(object)((Component)destructible).GetComponent<TreeBase>() != (Object)null || (Object)(object)((Component)destructible).GetComponent<TreeLog>() != (Object)null) { return false; } string text = MaterialFilters.PrefabName(((Component)destructible).gameObject).ToLowerInvariant(); if (!text.Contains("stub")) { return text.Contains("stump"); } return true; } } internal static class CivilPathPlanner { private readonly struct HeapEntry { internal readonly int Node; internal readonly float Score; internal HeapEntry(int node, float score) { Node = node; Score = score; } } private sealed class MinHeap { private readonly List<HeapEntry> _items = new List<HeapEntry>(); internal int Count => _items.Count; internal void Clear() { _items.Clear(); } internal void Push(HeapEntry entry) { _items.Add(entry); int num = _items.Count - 1; while (num > 0) { int num2 = (num - 1) / 2; if (_items[num2].Score <= entry.Score) { break; } _items[num] = _items[num2]; num = num2; } _items[num] = entry; } internal HeapEntry Pop() { HeapEntry result = _items[0]; HeapEntry value = _items[_items.Count - 1]; _items.RemoveAt(_items.Count - 1); if (_items.Count == 0) { return result; } int num = 0; while (true) { int num2 = num * 2 + 1; if (num2 >= _items.Count) { break; } int num3 = num2 + 1; int num4 = ((num3 < _items.Count && _items[num3].Score < _items[num2].Score) ? num3 : num2); if (_items[num4].Score >= value.Score) { break; } _items[num] = _items[num4]; num = num4; } _items[num] = value; return result; } } private const float BaseCellSize = 0.82f; private const float BodyRadius = 0.34f; private const float MaxStepHeight = 0.85f; private const int MaxExpandedNodes = 4000; private const float MaxSearchMilliseconds = 6f; private const float FrameBudgetMilliseconds = 8f; private const int BudgetCheckInterval = 64; private const int MaxSmoothingLookahead = 12; private static readonly Stopwatch SearchClock = new Stopwatch(); private static int _budgetFrame = -1; private static float _budgetUsedMilliseconds; private static readonly RaycastHit[] GroundHits = (RaycastHit[])(object)new RaycastHit[32]; private static readonly Collider[] ClearanceHits = (Collider[])(object)new Collider[32]; private static readonly int ObstacleMask = LayerMask.GetMask(new string[6] { "Default", "static_solid", "Default_small", "piece", "piece_nonsolid", "terrain" }); private static bool[] _evaluated = Array.Empty<bool>(); private static bool[] _walkable = Array.Empty<bool>(); private static bool[] _closed = Array.Empty<bool>(); private static float[] _heights = Array.Empty<float>(); private static float[] _costs = Array.Empty<float>(); private static int[] _parents = Array.Empty<int>(); private static readonly MinHeap Heap = new MinHeap(); internal static bool HasFrameBudget() { if (Time.frameCount != _budgetFrame) { _budgetFrame = Time.frameCount; _budgetUsedMilliseconds = 0f; } return _budgetUsedMilliseconds < 8f; } private static void ChargeFrameBudget(float milliseconds) { if (Time.frameCount != _budgetFrame) { _budgetFrame = Time.frameCount; _budgetUsedMilliseconds = 0f; } _budgetUsedMilliseconds += milliseconds; } private static void EnsureBuffers(int total) { if (_evaluated.Length < total) { int num = Mathf.NextPowerOfTwo(total); _evaluated = new bool[num]; _walkable = new bool[num]; _closed = new bool[num]; _heights = new float[num]; _costs = new float[num]; _parents = new int[num]; } else { Array.Clear(_evaluated, 0, total); Array.Clear(_walkable, 0, total); Array.Clear(_closed, 0, total); Array.Clear(_heights, 0, total); } } internal static bool TryBuildPath(Vector3 start, Vector3 goal, Transform mover, string actor, out List<Vector3> waypoints) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) waypoints = null; float num = Utils.DistanceXZ(start, goal); if (num < 1.25f) { waypoints = new List<Vector3> { goal }; return true; } if (!HasFrameBudget()) { return false; } SearchClock.Restart(); try { return RunSearch(start, goal, mover, actor, num, out waypoints); } finally { SearchClock.Stop(); ChargeFrameBudget((float)SearchClock.Elapsed.TotalMilliseconds); } } private static bool RunSearch(Vector3 start, Vector3 goal, Transform mover, string actor, float directDistance, out List<Vector3> waypoints) { //IL_001c: 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_0030: 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_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) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_017c: 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_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: 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_01df: Unknown result type (might be due to invalid IL or missing references) //IL_01e8: Unknown result type (might be due to invalid IL or missing references) //IL_01ed: Unknown result type (might be due to invalid IL or missing references) //IL_01f6: Unknown result type (might be due to invalid IL or missing references) //IL_01fb: Unknown result type (might be due to invalid IL or missing references) //IL_0204: Unknown result type (might be due to invalid IL or missing references) //IL_0209: Unknown result type (might be due to invalid IL or missing references) //IL_0212: Unknown result type (might be due to invalid IL or missing references) //IL_0217: Unknown result type (might be due to invalid IL or missing references) //IL_0220: 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_04c8: Unknown result type (might be due to invalid IL or missing references) //IL_0511: Unknown result type (might be due to invalid IL or missing references) //IL_029d: Unknown result type (might be due to invalid IL or missing references) //IL_02a2: Unknown result type (might be due to invalid IL or missing references) //IL_02a4: Unknown result type (might be due to invalid IL or missing references) //IL_02a6: Unknown result type (might be due to invalid IL or missing references) //IL_053a: Unknown result type (might be due to invalid IL or missing references) //IL_053f: Unknown result type (might be due to invalid IL or missing references) //IL_04f3: Unknown result type (might be due to invalid IL or missing references) //IL_02b6: Unknown result type (might be due to invalid IL or missing references) //IL_02b8: Unknown result type (might be due to invalid IL or missing references) //IL_02dc: Unknown result type (might be due to invalid IL or missing references) //IL_02e1: Unknown result type (might be due to invalid IL or missing references) //IL_041a: Unknown result type (might be due to invalid IL or missing references) //IL_041f: Unknown result type (might be due to invalid IL or missing references) waypoints = null; float num = Mathf.Clamp(directDistance * 0.58f, 8f, 24f); float num2 = Mathf.Min(start.x, goal.x) - num; float num3 = Mathf.Max(start.x, goal.x) + num; float num4 = Mathf.Min(start.z, goal.z) - num; float num5 = Mathf.Max(start.z, goal.z) + num; float num6 = 0.82f; int num7 = Mathf.CeilToInt((num3 - num2) / num6) + 1; int num8 = Mathf.CeilToInt((num5 - num4) / num6) + 1; int num9 = num7 * num8; if (num9 > 11000) { num6 *= Mathf.Sqrt((float)num9 / 11000f); num7 = Mathf.CeilToInt((num3 - num2) / num6) + 1; num8 = Mathf.CeilToInt((num5 - num4) / num6) + 1; num9 = num7 * num8; } EnsureBuffers(num9); bool[] evaluated = _evaluated; bool[] walkable = _walkable; bool[] closed = _closed; float[] heights = _heights; float[] costs = _costs; int[] parents = _parents; for (int i = 0; i < num9; i++) { costs[i] = float.MaxValue; parents[i] = -1; } int num10 = Mathf.Clamp(Mathf.RoundToInt((start.x - num2) / num6), 0, num7 - 1); int num11 = Mathf.Clamp(Mathf.RoundToInt((start.z - num4) / num6), 0, num8 - 1) * num7 + num10; evaluated[num11] = true; walkable[num11] = true; heights[num11] = start.y; costs[num11] = 0f; MinHeap heap = Heap; heap.Clear(); heap.Push(new HeapEntry(num11, directDistance)); int num12 = 0; int num13 = -1; bool flag = false; Vector2Int[] array = (Vector2Int[])(object)new Vector2Int[8] { new Vector2Int(1, 0), new Vector2Int(-1, 0), new Vector2Int(0, 1), new Vector2Int(0, -1), new Vector2Int(1, 1), new Vector2Int(1, -1), new Vector2Int(-1, 1), new Vector2Int(-1, -1) }; while (heap.Count > 0 && num12 < 4000) { int node = heap.Pop().Node; if (closed[node]) { continue; } closed[node] = true; num12++; if (num12 % 64 == 0 && SearchClock.Elapsed.TotalMilliseconds > 6.0) { flag = true; break; } int num14 = node % num7; int num15 = node / num7; Vector3 val = GridPoint(num14, num15, num2, num4, num6, heights[node]); if (Utils.DistanceXZ(val, goal) <= num6 * 1.5f && SegmentClear(val, goal, mover, num6)) { num13 = node; break; } Vector2Int[] array2 = array; for (int j = 0; j < array2.Length; j++) { Vector2Int val2 = array2[j]; int num16 = num14 + ((Vector2Int)(ref val2)).x; int num17 = num15 + ((Vector2Int)(ref val2)).y; if (num16 < 0 || num16 >= num7 || num17 < 0 || num17 >= num8) { continue; } int num18 = num17 * num7 + num16; if (closed[num18]) { continue; } float expectedHeight = heights[node]; if (!EvaluateNode(num18, num16, num17, num2, num4, num6, expectedHeight, mover, evaluated, walkable, heights)) { continue; } if (((Vector2Int)(ref val2)).x != 0 && ((Vector2Int)(ref val2)).y != 0) { int node2 = num15 * num7 + num16; int node3 = num17 * num7 + num14; if (!EvaluateNode(node2, num16, num15, num2, num4, num6, expectedHeight, mover, evaluated, walkable, heights) || !EvaluateNode(node3, num14, num17, num2, num4, num6, expectedHeight, mover, evaluated, walkable, heights)) { continue; } } float num19 = ((((Vector2Int)(ref val2)).x != 0 && ((Vector2Int)(ref val2)).y != 0) ? (num6 * 1.414214f) : num6); float num20 = Mathf.Abs(heights[num18] - heights[node]) * 1.5f; float num21 = costs[node] + num19 + num20; if (!(num21 >= costs[num18])) { costs[num18] = num21; parents[num18] = node; float num22 = Utils.DistanceXZ(GridPoint(num16, num17, num2, num4, num6, heights[num18]), goal); heap.Push(new HeapEntry(num18, num21 + num22)); } } } if (num13 < 0) { Diagnostics.Navigation("Hearthfolk[planner]: " + actor + " no physical route " + $"({directDistance:0.0}m, expanded={num12}" + (flag ? ", budget exhausted" : string.Empty) + ")"); return false; } List<Vector3> list = new List<Vector3> { goal }; int num23 = num13; while (num23 >= 0 && num23 != num11) { int x = num23 % num7; int z = num23 / num7; list.Add(GridPoint(x, z, num2, num4, num6, heights[num23])); num23 = parents[num23]; } list.Add(start); list.Reverse(); waypoints = Smooth(list, mover, num6); if (waypoints.Count > 0 && Utils.DistanceXZ(waypoints[0], start) < 0.65f) { waypoints.RemoveAt(0); } Diagnostics.Navigation("Hearthfolk[planner]: " + actor + " physical route " + $"{directDistance:0.0}m " + $"with {waypoints.Count} waypoint(s), expanded={num12}"); return waypoints.Count > 0; } internal static bool TryProjectWalkPoint(Vector3 desired, Transform mover, out Vector3 point) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000e: 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_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //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) //IL_0077: 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_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: 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) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: 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_019d: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_015c: 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_0168: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) Vector3[] obj = new Vector3[9] { Vector3.zero, Vector3.forward, Vector3.back, Vector3.right, Vector3.left, default(Vector3), default(Vector3), default(Vector3), default(Vector3) }; Vector3 val = new Vector3(1f, 0f, 1f); obj[5] = ((Vector3)(ref val)).normalized; val = new Vector3(1f, 0f, -1f); obj[6] = ((Vector3)(ref val)).normalized; val = new Vector3(-1f, 0f, 1f); obj[7] = ((Vector3)(ref val)).normalized; val = new Vector3(-1f, 0f, -1f); obj[8] = ((Vector3)(ref val)).normalized; Vector3[] array = (Vector3[])(object)obj; float[] array2 = new float[4] { 0f, 0.45f, 0.85f, 1.25f }; foreach (float num in array2) { Vector3[] array3 = array; foreach (Vector3 val2 in array3) { if (num == 0f && val2 != Vector3.zero) { continue; } Vector3 val3 = desired + val2 * num; if (TryGround(val3, desired.y, out var height) && !(Mathf.Abs(height - desired.y) > 2.5f)) { point = new Vector3(val3.x, height, val3.z); if (HasBodyClearance(point, mover)) { return true; } } } } point = desired; return false; } private static bool EvaluateNode(int node, int x, int z, float minX, float minZ, float cellSize, float expectedHeight, Transform mover, bool[] evaluated, bool[] walkable, float[] heights) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0066: 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) if (evaluated[node]) { if (walkable[node]) { return Mathf.Abs(heights[node] - expectedHeight) <= 0.85f; } return false; } evaluated[node] = true; Vector3 val = GridPoint(x, z, minX, minZ, cellSize, expectedHeight); if (!TryGround(val, expectedHeight, out var height)) { return false; } heights[node] = height; walkable[node] = Mathf.Abs(height - expectedHeight) <= 0.85f && HasBodyClearance(new Vector3(val.x, height, val.z), mover); return walkable[node]; } private static Vector3 GridPoint(int x, int z, float minX, float minZ, float cellSize, float y) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) return new Vector3(minX + (float)x * cellSize, y, minZ + (float)z * cellSize); } private static bool TryGround(Vector3 point, float expectedHeight, out float height) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_004c: 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_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) height = 0f; int num = Physics.RaycastNonAlloc(new Vector3(point.x, expectedHeight + 2.2f, point.z), Vector3.down, GroundHits, 4.8f, ObstacleMask, (QueryTriggerInteraction)1); float num2 = float.MaxValue; bool flag = false; for (int i = 0; i < num; i++) { RaycastHit val = GroundHits[i]; if (!((Object)(object)((RaycastHit)(ref val)).collider == (Object)null) && !((Object)(object)((Component)((RaycastHit)(ref val)).collider).GetComponentInParent<Character>() != (Object)null) && !(Vector3.Dot(((RaycastHit)(ref val)).normal, Vector3.up) < 0.55f)) { float num3 = Mathf.Abs(((RaycastHit)(ref val)).point.y - expectedHeight); if (!(num3 >= num2)) { height = ((RaycastHit)(ref val)).point.y; num2 = num3; flag = true; } } } if (flag) { return true; } if ((Object)(object)ZoneSystem.instance != (Object)null) { return ZoneSystem.instance.GetGroundHeight(point, ref height); } return false; } private static bool HasBodyClearance(Vector3 ground, Transform mover) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: 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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: 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_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) Vector3 val = ground + Vector3.up * 0.48f; Vector3 val2 = ground + Vector3.up * 1.55f; int num = Physics.OverlapCapsuleNonAlloc(val, val2, 0.34f, ClearanceHits, ObstacleMask, (QueryTriggerInteraction)1); for (int i = 0; i < num; i++) { Collider val3 = ClearanceHits[i]; if (!((Object)(object)val3 == (Object)null) && (!((Object)(object)mover != (Object)null) || !((Component)val3).transform.IsChildOf(mover)) && !((Object)(object)((Component)val3).GetComponentInParent<Character>() != (Object)null) && !((Object)(object)((Component)val3).GetComponentInParent<Heightmap>() != (Object)null)) { Bounds bounds = val3.bounds; if (!(((Bounds)(ref bounds)).max.y <= ground.y + 0.28f)) { return false; } } } return true; } private static bool SegmentClear(Vector3 from, Vector3 to, Transform mover, float cellSize) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0030: 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_0038: 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_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) float num = Utils.DistanceXZ(from, to); int num2 = Mathf.Max(1, Mathf.CeilToInt(num / (cellSize * 0.62f))); float num3 = from.y; for (int i = 1; i <= num2; i++) { float num4 = (float)i / (float)num2; Vector3 val = Vector3.Lerp(from, to, num4); if (!TryGround(val, num3, out var height) || Mathf.Abs(height - num3) > 0.85f || !HasBodyClearance(new Vector3(val.x, height, val.z), mover)) { return false; } num3 = height; } return true; } private static List<Vector3> Smooth(IReadOnlyList<Vector3> raw, Transform mover, float cellSize) { //IL_000b: 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_0038: 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) List<Vector3> list = new List<Vector3>(); int num = 0; list.Add(raw[0]); while (num < raw.Count - 1) { int num2 = num + 1; for (int num3 = Mathf.Min(raw.Count - 1, num + 12); num3 > num + 1; num3--) { if (SegmentClear(raw[num], raw[num3], mover, cellSize)) { num2 = num3; break; } } list.Add(raw[num2]); num = num2; } return list; } internal static float PathLength(IReadOnlyList<Vector3> path, Vector3 start) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001a: 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_0023: Unknown result type (might be due to invalid IL or missing references) float num = 0f; Vector3 val = start; foreach (Vector3 item in path) { num += Utils.DistanceXZ(val, item); val = item; } return num; } } [HarmonyPatch(typeof(Container), "Awake")] internal static class ContainerAwakePatch { [HarmonyPostfix] private static void Postfix(Container __instance) { ChestSortRules.Register(__instance); } } [HarmonyPatch(typeof(Container), "Interact")] internal static class ContainerInteractPatch { [HarmonyPrefix] private static bool Prefix(Container __instance, Humanoid character, bool hold, ref bool __result) { Player val = (Player)(object)((character is Player) ? character : null); if (hold || (Object)(object)val == (Object)null || (Object)(object)val != (Object)(object)Player.m_localPlayer || !ControlHeld() || !ChestSortRules.CanConfigure(__instance, val.GetPlayerID())) { return true; } ChestSortPanel.Toggle(__instance); __result = true; return false; } private static bool ControlHeld() { if (!Input.GetKey((KeyCode)306)) { return Input.GetKey((KeyCode)305); } return true; } } [HarmonyPatch(typeof(Container), "GetHoverText")] internal static class ContainerHoverPatch { [HarmonyPostfix] private static void Postfix(Container __instance, ref string __result) { if ((Object)(object)Player.m_localPlayer != (Object)null && ChestSortRules.IsStationaryPlayerChest(__instance)) { __result = __result + "\n" + Localization.instance.Localize("$hf_chest_sort_hover"); } } } internal static class Diagnostics { private const int NavigationLinesPerSecond = 12; private static float _navigationWindowStart; private static int _navigationWindowCount; private static int _navigationSuppressed; internal static bool Enabled { get { if (HfConfig.DebugLog != null) { return HfConfig.DebugLog.Value; } return false; } } internal static void Log(string message) { if (Enabled) { Logger.LogInfo((object)message); } } internal static void Navigation(string message) { if (Enabled) { Logger.LogInfo((object)message); return; } float unscaledTime = Time.unscaledTime; if (unscaledTime - _navigationWindowStart >= 1f) { _navigationWindowStart = unscaledTime; _navigationWindowCount = 0; if (_navigationSuppressed > 0) { int navigationSuppressed = _navigationSuppressed; _navigationSuppressed = 0; Logger.LogInfo((object)($"Hearthfolk[ai]: {navigationSuppressed} further navigation " + "message(s) suppressed; enable DebugLog for the full trace")); } } if (_navigationWindowCount >= 12) { _navigationSuppressed++; return; } _navigationWindowCount++; Logger.LogInfo((object)message); } } internal static class DormantSettlerRegistry { internal sealed class Record { internal readonly ZDO Zdo; internal ZDOID Id { get { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) if (Zdo == null) { return ZDOID.None; } return Zdo.m_uid; } } internal string Name { get { if (Zdo == null) { return Localization.instance.Localize("$hf_settler"); } return Zdo.GetString("hf_name", Localization.instance.Localize("$hf_settler")); } } internal SettlerRole Role { get { if (Zdo == null) { return SettlerRole.Idle; } return (SettlerRole)Zdo.GetInt("hf_role", 0); } } internal long RespawnAt { get { if (Zdo == null) { return 0L; } return Zdo.GetLong("hf_respawn_at", 0L); } } internal string StatusText => SettlerController.FormatRespawnStatus(RespawnAt); internal Record(ZDO zdo) { Zdo = zdo; } } private const float RefreshInterval = 0.75f; private static readonly List<ZDO> Cached = new List<ZDO>(); private static float _nextRefresh; internal static List<Record> ForHearth(ExilesHearth hearth, IEnumerable<ZDOID> instantiatedIds) { if ((Object)(object)hearth == (Object)null) { return new List<Record>(); } Refresh(); HashSet<ZDOID> liveIds = new HashSet<ZDOID>(instantiatedIds); return (from zdo in Cached where zdo.GetBool("hf_respawning", false) && BelongsTo(zdo, hearth) && !liveIds.Contains(zdo.m_uid) select new Record(zdo)).OrderBy<Record, string>((Record record) => record.Name, StringComparer.CurrentCultureIgnoreCase).ToList(); } internal static int CountForHearth(ExilesHearth hearth, bool forceRefresh = false) { if ((Object)(object)hearth == (Object)null) { return 0; } Refresh(forceRefresh); return Cached.Count((ZDO zdo) => BelongsTo(zdo, hearth)); } internal static void Invalidate() { _nextRefresh = 0f; } internal static void WakeExpired(ExilesHearth hearth) { //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_0101: 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_010b: 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_011a: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)hearth == (Object)null || !hearth.IsNetworkOwner || ZDOMan.instance == null || (Object)(object)ZNetScene.instance == (Object)null) { return; } Refresh(); long now = DateTime.UtcNow.Ticks; int num = 0; foreach (ZDO item in Cached.Where((ZDO zdo) => zdo.GetBool("hf_respawning", false) && BelongsTo(zdo, hearth) && zdo.GetLong("hf_respawn_at", 0L) <= now)) { if (!((Object)(object)ZNetScene.instance.FindInstance(item.m_uid) != (Object)null)) { if (!item.HasOwner()) { item.SetOwner(ZDOMan.GetSessionID()); } if (item.IsOwner()) { Vector3 position = ((Component)hearth).transform.position + ((Component)hearth).transform.right * (2.2f + (float)num * 0.65f) + Vector3.up * 0.5f; item.SetPosition(position); item.Set("hf_home", HomeFor(item, hearth)); num++; Diagnostics.Log($"Hearthfolk[respawn]: waking unloaded settler ZDO {item.m_uid}"); } } } } internal static void RecallDisconnectedFollowers(ExilesHearth hearth) { //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_015c: 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_017f: 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) if ((Object)(object)hearth == (Object)null || !hearth.IsNetworkOwner || ZDOMan.instance == null || (Object)(object)ZNetScene.instance == (Object)null) { return; } Refresh(); int num = 0; foreach (ZDO item in Cached.Where((ZDO zdo) => BelongsTo(zdo, hearth) && zdo.GetInt("hf_role", 0) == 5 && zdo.GetInt("hf_follower_mode", 0) == 1 && zdo.GetLong("hf_follower_target", 0L) != 0)) { long num2 = item.GetLong("hf_follower_target", 0L); if (SettlerController.IsPlayerConnected(num2) || (Object)(object)ZNetScene.instance.FindInstance(item.m_uid) != (Object)null) { continue; } Vector3 val = HomeFor(item, hearth); if (!(Vector3.Distance(item.GetPosition(), val) <= 6f) || !(item.GetString("hf_status", string.Empty) == "$hf_status_follower_waiting_for_player")) { if (!item.HasOwner()) { item.SetOwner(ZDOMan.GetSessionID()); } if (item.IsOwner()) { Vector3 position = val + ((Component)hearth).transform.right * (2.2f + (float)num * 0.65f) + Vector3.up * 0.5f; item.Set("hf_home", val); item.Set("hf_status", "$hf_status_follower_waiting_for_player"); item.SetPosition(position); num++; Diagnostics.Log($"Hearthfolk[follower]: recalled unloaded settler ZDO {item.m_uid} " + $"while preserving player {num2}"); } } } } private static bool BelongsTo(ZDO zdo, ExilesHearth hearth) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: 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_004a: 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_006c: Unknown result type (might be due to invalid IL or missing references) if (zdo == null || !zdo.IsValid()) { return false; } long num = zdo.GetLong("hf_owner", 0L); if (num != 0L && hearth.OwnerId != 0L && num != hearth.OwnerId) { return false; } Vector3 vec = zdo.GetVec3("hf_home", zdo.GetPosition()); if (Vector3.Distance(vec, ((Component)hearth).transform.position) <= 6f) { return true; } if ((Object)(object)ExilesHearth.FindFor(vec, num) == (Object)null) { return (Object)(object)ExilesHearth.AdoptionCandidateFor(vec, num) == (Object)(object)hearth; } return false; } private static Vector3 HomeFor(ZDO zdo, ExilesHearth hearth) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) Vector3 vec = zdo.GetVec3("hf_home", ((Component)hearth).transform.position); if (!(Vector3.Distance(vec, ((Component)hearth).transform.position) <= 6f)) { return ((Component)hearth).transform.position; } return vec; } private static void Refresh(bool force = false) { if ((force || !(Time.unscaledTime < _nextRefresh)) && ZDOMan.instance != null) { _nextRefresh = Time.unscaledTime + 0.75f; List<ZDO> list = new List<ZDO>(); int num = 0; bool flag = false; int num2 = 0; while (!flag && num2++ < 2048) { flag = ZDOMan.instance.GetAllZDOsWithPrefabIterative("hf_settler", list, ref num); } Cached.Clear(); Cached.AddRange(from zdo in list where zdo != null && zdo.IsValid() group zdo by zdo.m_uid into @group select @group.First()); } } } internal sealed class ExilesHearth : MonoBehaviour, Interactable, Hoverable { private sealed class SavedRouteEntry { internal ZDOID Id; internal Vector3 Position; internal string Prefab; internal long Creator; } internal static readonly List<ExilesHearth> Instances = new List<ExilesHearth>(); private static readonly string[] SettlerNames = new string[12] { "Astrid", "Birger", "Eira", "Freydis", "Gorm", "Hakon", "Ingrid", "Kari", "Leif", "Runa", "Sigrid", "Torsten" }; private ZNetView _nview; private Piece _piece; private float _nextDormantSettlerCheck; private List<Door> _availableGatewayCache; private float _availableGatewayCacheAt; private List<Container> _intakeStorageCache; private float _intakeStorageCacheUntil; private bool _intakeReported; private const float HearthRecoveryRadius = 0.85f; internal ZDOID PersistentId { get { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_nview != (Object)null) || !_nview.IsValid()) { return ZDOID.None; } return _nview.GetZDO().m_uid; } } internal bool IsNetworkOwner { get { if ((Object)(object)_nview != (Object)null && _nview.IsValid()) { return _nview.IsOwner(); } return false; } } internal long OwnerId { get { if (!((Object)(object)_piece != (Object)null)) { return 0L; } return _piece.GetCreator(); } } internal bool AlertActive { get { if ((Object)(object)_nview != (Object)null && _nview.IsValid()) { return _nview.GetZDO().GetBool("hf_settlement_alert", false); } return false; } } internal bool RaidActive => RaidAt(((Component)this).transform.position); internal bool DefenseThreatActive { get { if ((Object)(object)_nview != (Object)null && _nview.IsValid()) { return _nview.GetZDO().GetLong("hf_defense_threat_until", 0L) > DateTime.UtcNow.Ticks; } return false; } } internal List<Vector3> PatrolRoute => PatrolPoint.RouteFor(this); internal int PatrolPointCount => PatrolRoute.Count; internal int AvailablePatrolPointCount => PatrolPoint.PointsFor(this).Count; internal List<PatrolPoint> AvailablePatrolPoints => PatrolPoint.PointsFor(this); internal bool PatrolRouteConfigured { get { if ((Object)(object)_nview != (Object)null && _nview.IsValid()) { return _nview.GetZDO().GetBool("hf_patrol_route_configured", false); } return false; } } internal List<ZDOID> SavedPatrolRoute => ResolveSavedRoute("hf_patrol_route", "hf_patrol_route_identity", PatrolPoint.PointsFor(this).Select(PatrolRouteEntry), "patrol"); internal List<ZDOID> CurrentPatrolRouteIds => PatrolPoint.RouteIdsFor(this); internal bool GatewayDoorsConfigured { get { if (!((Object)(object)_nview != (Object)null) || !_nview.IsValid() || !_nview.GetZDO().GetBool("hf_gateway_doors_configured", false)) { return TaggedGatewayDoors().Count > 0; } return true; } } internal List<ZDOID> SavedGatewayDoorIds { get { List<ZDOID> list = ResolveSavedRoute("hf_gateway_doors", "hf_gateway_doors_identity", AvailableGatewayDoors.Select(GatewayRouteEntry), "gateway"); List<Door> list2 = TaggedGatewayDoors(); if (list.Count > 0) { if (list2.Count == 0 && (Object)(object)_nview != (Object)null && _nview.IsValid() && _nview.IsOwner()) { PersistGatewayMarkers(AvailableGatewayDoors, list); } return list; } if (list2.Count == 0) { return list; } List<ZDOID> list3 = list2.Select((Door door) => door.m_nview.GetZDO().m_uid).Distinct().Take(32) .ToList(); if ((Object)(object)_nview != (Object)null && _nview.IsValid() && _nview.IsOwner()) { ZDO zDO = _nview.GetZDO(); zDO.Set("hf_gateway_doors", EncodePatrolRoute(list3)); StoreRouteIdentity(zDO, "hf_gateway_doors_identity", list3, list2.Select(GatewayRouteEntry)); zDO.Set("hf_gateway_doors_configured", true); Logger.LogInfo((object)$"Hearthfolk[gateway]: restored {list3.Count} entrance(s) from their door markers."); } return list3; } } internal List<Door> AvailableGatewayDoors { get { if (_availableGatewayCache == null || Time.time >= _availableGatewayCacheAt) { _availableGatewayCache = FindAvailableGatewayDoors(); _availableGatewayCacheAt = Time.time + 1f; } return _availableGatewayCache; } } internal int AvailableGatewayDoorCount => AvailableGatewayDoors.Count; internal List<Door> ConfiguredGatewayDoors { get { Dictionary<ZDOID, Door> byId = AvailableGatewayDoors.Where((Door door) => (Object)(object)door?.m_nview != (Object)null && door.m_nview.IsValid()).ToDictionary((Door door) => door.m_nview.GetZDO().m_uid); return (from id in SavedGatewayDoorIds.Where(byId.ContainsKey) select byId[id]).ToList(); } } internal ZDOID IntakeStorageId { get { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) Container? obj = ResolveIntakeStorages().FirstOrDefault(); ZDOID? obj2; if (obj == null) { obj2 = null; } else { ZNetView nview = obj.m_nview; obj2 = ((nview != null) ? new ZDOID?(nview.GetZDO().m_uid) : ((ZDOID?)null)); } return (ZDOID)(((??)obj2) ?? ZDOID.None); } } internal bool HasIntakeStorage => ResolveIntakeStorages().Count > 0; internal int RecruitCost => NextRecruitCost(forceRefresh: false); private void Awake() { _nview = ((Component)this).GetComponent<ZNetView>(); _piece = ((Component)this).GetComponent<Piece>(); if ((Object)(object)_nview != (Object)null && _nview.IsValid()) { _nview.Register<long>("hf_ToggleSettlementAlert", (Action<long, long>)RPC_ToggleAlert); _nview.Register("hf_SignalDefenseThreat", (Action<long>)RPC_SignalDefenseThreat); _nview.Register<long, int, string>("hf_SetPatrolRoute", (Action<long, long, int, string>)RPC_SetPatrolRoute); _nview.Register<long, ZDOID>("hf_SetIntakeStorage", (Action<long, long, ZDOID>)RPC_SetIntakeStorage); _nview.Register<long, ZDOID, int>("hf_SetIntakeStorageRoles", (Action<long, long, ZDOID, int>)RPC_SetIntakeStorageRoles); _nview.Register<long, int, string>("hf_SetGatewayDoors", (Action<long, long, int, string>)RPC_SetGatewayDoors); } if (!Instances.Contains(this)) { Instances.Add(this); } } private void OnDestroy() { Instances.Remove(this); } private void Update() { if (!(Time.time < _nextDormantSettlerCheck)) { _nextDormantSettlerCheck = Time.time + 1f; DormantSettlerRegistry.WakeExpired(this); DormantSettlerRegistry.RecallDisconnectedFollowers(this); } } internal bool CanManage(long requesterId) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) return SettlementAccess.CanManage(OwnerId, requesterId, ((Component)this).transform.position); } private bool CanManageRequest(long sender, long requesterId, string action) { if (NetworkRequest.AuthenticatePlayer(sender, requesterId, action)) { return CanManage(requesterId); } return false; } public float GetHoverOffset() { return 0f; } public string GetHoverName() { return Localization.instance.Localize("$piece_hf_hearth"); } public string GetHoverText() { return Localization.instance.Localize("$piece_hf_hearth\n[<color=yellow><b>$KEY_Use</b></color>] $hf_manage"); } public bool Interact(Humanoid user, bool hold, bool alt) { if (!hold) { Player val = (Player)(object)((user is Player) ? user : null); if (val != null && !((Object)(object)val != (Object)(object)Player.m_localPlayer)) { if ((Object)(object)_nview == (Object)null || !_nview.IsValid()) { return false; } if (!CanManage(val.GetPlayerID())) { ((Character)val).Message((MessageType)2, "$msg_cantopen", 0, (Sprite)null, false); return true; } HearthPanel.Toggle(this); return true; } } return false; } private int NextRecruitCost(bool forceRefresh) { return HfConfig.RecruitmentCost(RecruitmentCount(forceRefresh)); } private int RecruitmentCount(bool forceRefresh) { ZDO val = (((Object)(object)_nview != (Object)null && _nview.IsValid()) ? _nview.GetZDO() : null); if (val == null) { return 0; } int num = val.GetInt("hf_recruitment_count", -1); if (num >= 0) { if (!forceRefresh) { return num; } int num2 = DormantSettlerRegistry.CountForHearth(this, forceRefresh: true); if (num2 > num) { StoreRecruitmentCount(num2); return num2; } return num; } int num3 = DormantSettlerRegistry.CountForHearth(this, forceRefresh); StoreRecruitmentCount(num3); return num3; } private void StoreRecruitmentCount(int count) { if (!((Object)(object)_nview == (Object)null) && _nview.IsValid()) { if (!_nview.IsOwner()) { _nview.ClaimOwnership(); } if (_nview.IsOwner()) { _nview.GetZDO().Set("hf_recruitment_count", Mathf.Max(0, count)); } } } internal void RequestToggleAlert() { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)null && (Object)(object)_nview != (Object)null && _nview.IsValid()) { _nview.InvokeRPC("hf_ToggleSettlementAlert", new object[1] { localPlayer.GetPlayerID() }); } } private void RPC_ToggleAlert(long sender, long requesterId) { if (_nview.IsOwner() && CanManageRequest(sender, requesterId, "settlement alert change")) { ZDO zDO = _nview.GetZDO(); zDO.Set("hf_settlement_alert", !zDO.GetBool("hf_settlement_alert", false)); } } internal void RequestSetPatrolRoute(IList<ZDOID> route) { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null) && !((Object)(object)_nview == (Object)null) && _nview.IsValid()) { _nview.InvokeRPC("hf_SetPatrolRoute", new object[3] { localPlayer.GetPlayerID(), 1, EncodePatrolRoute(route) }); } } internal void RequestAutomaticPatrolRoute() { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null) && !((Object)(object)_nview == (Object)null) && _nview.IsValid()) { _nview.InvokeRPC("hf_SetPatrolRoute", new object[3] { localPlayer.GetPlayerID(), 0, string.Empty }); } } private void RPC_SetPatrolRoute(long sender, long requesterId, int configured, string encodedRoute) { if (!_nview.IsOwner() || !CanManageRequest(sender, requesterId, "settlement patrol route change")) { return; } ZDO zDO = _nview.GetZDO(); if (configured == 0) { zDO.Set("hf_patrol_route_configured", false); zDO.Set("hf_patrol_route", string.Empty); zDO.Set("hf_patrol_route_identity", string.Empty); return; } List<PatrolPoint> source = PatrolPoint.PointsFor(this); HashSet<ZDOID> validIds = new HashSet<ZDOID>(source.Select((PatrolPoint point) => point.PersistentId)); List<ZDOID> list = (from id in DecodePatrolRoute(encodedRoute) where id != ZDOID.None && validIds.Contains(id) select id).Distinct().Take(64).ToList(); zDO.Set("hf_patrol_route", EncodePatrolRoute(list)); StoreRouteIdentity(zDO, "hf_patrol_route_identity", list, source.Select(PatrolRouteEntry)); zDO.Set("hf_patrol_route_configured", true); Diagnostics.Log($"Hearthfolk[patrol]: saved {list.Count} persistent route point(s)."); } internal void RequestSetGatewayDoors(IList<ZDOID> doors) { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null) && !((Object)(object)_nview == (Object)null) && _nview.IsValid()) { _nview.InvokeRPC("hf_SetGatewayDoors", new object[3] { localPlayer.GetPlayerID(), 1, EncodePatrolRoute(doors) }); } } internal void RequestAutomaticGatewayDoors() { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null) && !((Object)(object)_nview == (Object)null) && _nview.IsValid()) { _nview.InvokeRPC("hf_SetGatewayDoors", new object[3] { localPlayer.GetPlayerID(), 0, string.Empty }); } } private void RPC_SetGatewayDoors(long sender, long requesterId, int configured, string encodedDoors) { if (!_nview.IsOwner() || !CanManageRequest(sender, requesterId, "settlement gateway change")) { return; } ZDO zDO = _nview.GetZDO(); if (configured == 0) { ClearGatewayMarkers(AvailableGatewayDoors); zDO.Set("hf_gateway_doors_configured", false); zDO.Set("hf_gateway_doors", string.Empty); zDO.Set("hf_gateway_doors_identity", string.Empty); return; } List<Door> availableGatewayDoors = AvailableGatewayDoors; HashSet<ZDOID> validIds = new HashSet<ZDOID>(from door in availableGatewayDoors where (Object)(object)door?.m_nview != (Object)null && door.m_nview.IsValid() select door.m_nview.GetZDO().m_uid); List<ZDOID> list = (from id in DecodePatrolRoute(encodedDoors) where id != ZDOID.None && validIds.Contains(id) select id).Distinct().Take(32).ToList(); if (list.Count != 0) { zDO.Set("hf_gateway_doors", EncodePatrolRoute(list)); StoreRouteIdentity(zDO, "hf_gateway_doors_identity", list, availableGatewayDoors.Select(GatewayRouteEntry)); zDO.Set("hf_gateway_doors_configured", true); PersistGatewayMarkers(availableGatewayDoors, list); Logger.LogInfo((object)$"Hearthfolk[gateway]: saved {list.Count} persistent entrance(s)."); } } private List<Door> TaggedGatewayDoors() { return AvailableGatewayDoors.Where(GatewayMarkerMatches).ToList(); } private bool GatewayMarkerMatches(Door door) { //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_0068: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)door?.m_nview == (Object)null || !door.m_nview.IsValid()) { return false; } ZDO zDO = door.m_nview.GetZDO(); if (zDO.GetBool("hf_gateway_marker", false) && zDO.GetLong("hf_gateway_creator", 0L) == OwnerId) { return Vector3.Distance(zDO.GetVec3("hf_gateway_hearth", Vector3.zero), ((Component)this).transform.position) <= 0.75f; } return false; } private void PersistGatewayMarkers(IEnumerable<Door> available, ICollection<ZDOID> selected) { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) HashSet<ZDOID> hashSet = new HashSet<ZDOID>(selected); foreach (Door item in available) { if ((Object)(object)item?.m_nview == (Object)null || !item.m_nview.IsValid()) { continue; } ZDO zDO = item.m_nview.GetZDO(); bool flag = hashSet.Contains(zDO.m_uid); if (flag || GatewayMarkerMatches(item)) { if (!item.m_nview.IsOwner()) { item.m_nview.ClaimOwnership(); } if (!item.m_nview.IsOwner()) { Logger.LogWarning((object)("Hearthfolk[gateway]: could not persist marker on " + ((Object)item).name + "; door is owned by another peer.")); continue; } zDO = item.m_nview.GetZDO(); zDO.Set("hf_gateway_marker", flag); zDO.Set("hf_gateway_hearth", flag ? ((Component)this).transform.position : Vector3.zero); zDO.Set("hf_gateway_creator", flag ? OwnerId : 0); } } } private void ClearGatewayMarkers(IEnumerable<Door> available) { PersistGatewayMarkers(available, new List<ZDOID>()); } internal List<Container> ResolveIntakeStorages(Component self = null) { //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_nview == (Object)null || !_nview.IsValid()) { return new List<Container>(); } if (_intakeStorageCache == null || Time.time >= _intakeStorageCacheUntil) { _intakeStorageCache = (from container in SceneObjectCache.Get<Container>(1f) where (Object)(object)container != (Object)null && (Object)(object)container.m_nview != (Object)null && container.m_nview.IsValid() && ChestSortRules.IsStationaryPlayerChest(container) && BelongsToThisHearth(container.m_nview.GetZDO()) select container).ToList(); Container val = StorageLink.Resolve(_nview.GetZDO(), (Component)(object)this); if ((Object)(object)val != (Object)null && !_intakeStorageCache.Contains(val)) { _intakeStorageCache.Add(val); } _intakeStorageCacheUntil = Time.time + 1f; ReportIntakeOnce(); } Vector3 origin = (((Object)(object)self != (Object)null) ? self.transform.position : ((Component)this).transform.position); return (from container in _intakeStorageCache where (Object)(object)container != (Object)null && ((Component)container).gameObject.activeInHierarchy orderby Vector3.Distance(origin, ((Component)container).transform.position) select container).ToList(); } private void ReportIntakeOnce() { //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_011b: 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) if (_intakeReported || (Object)(object)_nview == (Object)null || !_nview.IsValid()) { return; } _intakeReported = true; float num = Mathf.Max(18f, (HfConfig.WorkRadius != null) ? HfConfig.WorkRadius.Value : 30f); Container[] array = SceneObjectCache.Get<Container>(1f); foreach (Container val in array) { if (!((Object)(object)val?.m_nview == (Object)null) && val.m_nview.IsValid()) { ZDO zDO = val.m_nview.GetZDO(); int num2 = zDO.GetInt("hf_intake_roles", 0); if (num2 != 0 && !(Utils.DistanceXZ(((Component)this).transform.position, zDO.GetPosition()) > num)) { ZDOID zDOID = zDO.GetZDOID("hf_intake_hearth"); Logger.LogInfo((object)($"Hearthfolk[storage]: chest {zDO.m_uid} carries roles={num2} " + $"hearth={zDOID}, this hearth is {PersistentId}, " + string.Format("identity={0}", zDO.GetVec3("hf_intake_hearth_pos", Vector3.zero)))); } } } } internal Container ResolveIntakeStorage(Component self = null) { SettlerController settlerController = self as SettlerController; if (!((Object)(object)settlerController != (Object)null)) { return ResolveIntakeStorages(self).FirstOrDefault(); } return ResolveRoleIntakeStorages(settlerController).FirstOrDefault(); } internal List<Container> ResolveRoleIntakeStorages(SettlerController settler) { List<Container> list = ResolveIntakeStorages((Component)(object)settler); if ((Object)(object)settler == (Object)null || settler.CurrentRole == SettlerRole.Caretaker) { return list; } IntakeRoles required = IntakeRoleFor(settler.CurrentRole); return list.Where((Container container) => (IntakeRolesFor(container) & required) != 0).ToList(); } internal bool HasIntakeStorageFor(SettlerRole role) { if (role == SettlerRole.Caretaker) { return HasIntakeStorage; } IntakeRoles required = IntakeRoleFor(role); if (required != IntakeRoles.None) { return ResolveIntakeStorages().Any((Container container) => (IntakeRolesFor(container) & required) != 0); } return false; } internal IntakeRoles IntakeRolesFor(Container container) { //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)container?.m_nview == (Object)null || !container.m_nview.IsValid()) { return IntakeRoles.None; } ZDO zDO = container.m_nview.GetZDO(); if (BelongsToThisHearth(zDO)) { return (IntakeRoles)(zDO.GetInt("hf_intake_roles", 0) & 0x1F); } if (!(StorageLink.GetId(_nview.GetZDO()) == zDO.m_uid)) { return IntakeRoles.None; } return IntakeRoles.All; } private bool BelongsToThisHearth(ZDO chestZdo) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: 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_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) if (chestZdo.GetInt("hf_intake_roles", 0) == 0) { return false; } if (chestZdo.GetZDOID("hf_intake_hearth") == PersistentId) { return true; } Vector3 vec = chestZdo.GetVec3("hf_intake_hearth_pos", Vector3.zero); if (vec == Vector3.zero) { return AdoptOrphanedIntake(chestZdo); } long num = chestZdo.GetLong("hf_intake_hearth_creator", 0L); if (Vector3.Distance(vec, ((Component)this).transform.position) > 0.85f || (num != 0L && OwnerId != 0L && num != OwnerId)) { return false; } HealIntakeReference(chestZdo); return true; } private bool AdoptOrphanedIntake(ZDO chestZdo) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005b: 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_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) ZDOID zDOID = chestZdo.GetZDOID("hf_intake_hearth"); if (zDOID == ZDOID.None || !chestZdo.IsOwner() || OwnerId == 0L) { return false; } float num = Mathf.Max(18f, (HfConfig.WorkRadius != null) ? HfConfig.WorkRadius.Value : 30f); Vector3 position = chestZdo.GetPosition(); if (Utils.DistanceXZ(((Component)this).transform.position, position) > num) { return false; } foreach (ExilesHearth instance in Instances) { if (!((Object)(object)instance == (Object)null) && !(instance.PersistentId == ZDOID.None)) { if (instance.PersistentId == zDOID) { return false; } if ((Object)(object)instance != (Object)(object)this && instance.OwnerId == OwnerId && Utils.DistanceXZ(((Component)instance).transform.position, position) <= num) { return false; } } } Logger.LogInfo((object)($"Hearthfolk[storage]: adopted intake chest {chestZdo.m_uid}, " + $"assigned to a hearth id ({zDOID}) that no longer exists after " + "a world load")); chestZdo.Set("hf_intake_hearth", PersistentId); chestZdo.Set("hf_intake_hearth_pos", ((Component)this).transform.position); chestZdo.Set("hf_intake_hearth_creator", OwnerId); _intakeStorageCache = null; _intakeStorageCacheUntil = 0f; return true; } private void HealIntakeReference(ZDO chestZdo) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0014: 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_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) if (chestZdo.IsOwner() && !(chestZdo.GetZDOID("hf_intake_hearth") == PersistentId)) { Logger.LogInfo((object)($"Hearthfolk[storage]: intake chest {chestZdo.m_uid} reconnected to " + string.Format("this hearth by position ({0} ", chestZdo.GetZDOID("hf_intake_hearth")) + $"-> {PersistentId})")); chestZdo.Set("hf_intake_hearth", PersistentId); _intakeStorageCache = null; _intakeStorageCacheUntil = 0f; } } internal void RequestSetIntakeStorage(Container container) { RequestSetIntakeStorageRoles(container, IntakeRoles.All); } internal void RequestSetIntakeStorageRoles(Container container, IntakeRoles roles) { //IL_008c: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null) && !((Object)(object)container?.m_nview == (Object)null) && container.m_nview.IsValid() && !((Object)(object)_nview == (Object)null) && _nview.IsValid() && !((Object)(object)IntakeCandidateFor(container, localPlayer.GetPlayerID()) != (Object)(object)this)) { _nview.InvokeRPC("hf_SetIntakeStorageRoles", new object[3] { localPlayer.GetPlayerID(), container.m_nview.GetZDO().m_uid, (int)(roles & IntakeRoles.All) }); } } private bool TakeRequestOwnership() { if (_nview.IsOwner()) { return true; } _nview.ClaimOwnership(); return _nview.IsOwner(); } private void RPC_SetIntakeStorage(long sender, long requesterId, ZDOID containerId) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_nview == (Object)null) && _nview.IsValid() && CanManageRequest(sender, requesterId, "settlement intake assignment") && !((Object)(object)ZNetScene.instance == (Object)null) && TakeRequestOwnership()) { GameObject val = ZNetScene.instance.FindInstance(containerId); Container val2 = (((Object)(object)val != (Object)null) ? (val.GetComponent<Container>() ?? val.GetComponentInChildren<Container>(true)) : null); if (ChestSortRules.IsStationaryPlayerChest(val2) && val2.CheckAccess(requesterId) && !((Object)(object)IntakeHearthWithinRange(val2, requesterId) != (Object)(object)this)) { SetIntakeStorageRoles(val2, IntakeRoles.All); } } } private void RPC_SetIntakeStorageRoles(long sender, long requesterId, ZDOID containerId, int requestedRoles) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_nview == (Object)null) && _nview.IsValid() && CanManageRequest(sender, requesterId, "settlement intake role change") && !((Object)(object)ZNetScene.instance == (Object)null) && TakeRequestOwnership()) { GameObject val = ZNetScene.instance.FindInstance(containerId); Container val2 = (((Object)(object)val != (Object)null) ? (val.GetComponent<Container>() ?? val.GetComponentInChildren<Container>(true)) : null); if (ChestSortRules.IsStationaryPlayerChest(val2) && val2.CheckAccess(requesterId) && !((Object)(object)IntakeHearthWithinRange(val2, requesterId) != (Object)(object)this)) { SetIntakeStorageRoles(val2, (IntakeRoles)(requestedRoles & 0x1F)); } } } private void SetIntakeStorageRoles(Container container, IntakeRoles roles) { //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)container?.m_nview == (Object)null) && container.m_nview.IsValid()) { Container val = StorageLink.Resolve(_nview.GetZDO(), (Component)(object)this); if ((Object)(object)val?.m_nview != (Object)null && val.m_nview.IsValid() && (Object)(object)val != (Object)(object)container) { SetPhysicalIntakeRoles(val, IntakeRoles.All); } StorageLink.Clear(_nview.GetZDO()); bool num = SetPhysicalIntakeRoles(container, roles); _intakeStorageCache = null; _intakeStorageCacheUntil = 0f; if (num) { Logger.LogInfo((object)($"Hearthfolk[storage]: intake chest {container.m_nview.GetZDO().m_uid} " + $"roles={(int)roles} hearth={PersistentId} persisted")); } } } private bool SetPhysicalIntakeRoles(Container container, IntakeRoles roles) { //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: 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_0078: 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) if (!container.m_nview.IsOwner()) { container.m_nview.ClaimOwnership(); if (!container.m_nview.IsOwner()) { Logger.LogWarning((object)("Hearthfolk[storage]: intake roles for chest " + $"{container.m_nview.GetZDO().m_uid} not written; the chest " + "is owned by another peer")); return false; } } ZDO zDO = container.m_nview.GetZDO(); if (roles == IntakeRoles.None) { if (BelongsToThisHearth(zDO)) { zDO.Set("hf_intake_hearth", ZDOID.None); zDO.Set("hf_intake_roles", 0); zDO.Set("hf_intake_hearth_pos", Vector3.zero); zDO.Set("hf_intake_hearth_creator", 0L); } return true; } zDO.Set("hf_intake_hearth", PersistentId); zDO.Set("hf_intake_roles", (int)(roles & IntakeRoles.All)); zDO.Set("hf_intake_hearth_pos", ((Component)this).transform.position); zDO.Set("hf_intake_hearth_creator", OwnerId); return true; } private static IntakeRoles IntakeRoleFor(SettlerRole role) { return role switch { SettlerRole.Lumberjack => IntakeRoles.Lumberjack, SettlerRole.Miner => IntakeRoles.Miner, SettlerRole.Farmer => IntakeRoles.Farmer, SettlerRole.Forager => IntakeRoles.Forager, SettlerRole.Hunter => IntakeRoles.Hunter, _ => IntakeRoles.None, }; } private List<ZDOID> ResolveSavedRoute(string routeKey, string identityKey, IEnumerable<SavedRouteEntry> available, string label) { //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: Unknown result type (might