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 Companions v1.2.4
plugins/Companions.dll
Decompiled an hour 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.Concurrent; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; using System.IO.Compression; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using System.Threading; using AzuEPI; using AzuEPI.Core.Slots; using AzuExtendedPlayerInventory; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BiomeLockAPI; using HarmonyLib; using ItemManager; using JetBrains.Annotations; using LocalizationManager; using Microsoft.CodeAnalysis; using PieceManager; using ServerSync; using Splatform; using TMPro; using UnityEngine; using UnityEngine.Audio; using UnityEngine.UI; using YamlDotNet.Core; using YamlDotNet.Core.Events; using YamlDotNet.Core.ObjectPool; using YamlDotNet.Core.Tokens; using YamlDotNet.Helpers; using YamlDotNet.Serialization; using YamlDotNet.Serialization.BufferedDeserialization; using YamlDotNet.Serialization.BufferedDeserialization.TypeDiscriminators; using YamlDotNet.Serialization.Callbacks; using YamlDotNet.Serialization.Converters; using YamlDotNet.Serialization.EventEmitters; using YamlDotNet.Serialization.NamingConventions; using YamlDotNet.Serialization.NodeDeserializers; using YamlDotNet.Serialization.NodeTypeResolvers; using YamlDotNet.Serialization.ObjectFactories; using YamlDotNet.Serialization.ObjectGraphTraversalStrategies; using YamlDotNet.Serialization.ObjectGraphVisitors; using YamlDotNet.Serialization.Schemas; using YamlDotNet.Serialization.TypeInspectors; using YamlDotNet.Serialization.TypeResolvers; using YamlDotNet.Serialization.Utilities; using YamlDotNet.Serialization.ValueDeserializers; [assembly: Guid("E74EB49A-461D-48EA-85BC-F462D60C98C4")] [assembly: ComVisible(false)] [assembly: AssemblyTrademark("")] [assembly: AssemblyCopyright("Copyright © 2025")] [assembly: AssemblyProduct("Companions")] [assembly: AssemblyCompany("Radamanto")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyDescription("")] [assembly: AssemblyTitle("Companions")] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: CompilationRelaxations(8)] [assembly: AssemblyFileVersion("1.2.4")] [assembly: AssemblyConfiguration("")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.2.4.0")] [module: <63defa34-6191-49c3-b1ce-ecdd5794c0b8>RefSafetyRules(11)] [module: UnverifiableCode] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [<3be3cbfa-9b42-411b-84f6-4e6f7d2ef607>Embedded] internal sealed class <3be3cbfa-9b42-411b-84f6-4e6f7d2ef607>EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] [<3be3cbfa-9b42-411b-84f6-4e6f7d2ef607>Embedded] [CompilerGenerated] internal sealed class <51d574fa-9559-41c7-ba50-f30c8017450e>NullableAttribute : Attribute { public readonly byte[] NullableFlags; public <51d574fa-9559-41c7-ba50-f30c8017450e>NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public <51d574fa-9559-41c7-ba50-f30c8017450e>NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] [CompilerGenerated] [<3be3cbfa-9b42-411b-84f6-4e6f7d2ef607>Embedded] internal sealed class <7664ba2c-c0fb-485d-95cb-d6607104ddd1>NullableContextAttribute : Attribute { public readonly byte Flag; public <7664ba2c-c0fb-485d-95cb-d6607104ddd1>NullableContextAttribute(byte P_0) { Flag = P_0; } } [<3be3cbfa-9b42-411b-84f6-4e6f7d2ef607>Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] [CompilerGenerated] internal sealed class <63defa34-6191-49c3-b1ce-ecdd5794c0b8>RefSafetyRulesAttribute : Attribute { public readonly int Version; public <63defa34-6191-49c3-b1ce-ecdd5794c0b8>RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace Companions { internal enum CompanionCollectionMode { MarkedItems, AllItems, None } [<51d574fa-9559-41c7-ba50-f30c8017450e>Nullable(0)] [<7664ba2c-c0fb-485d-95cb-d6607104ddd1>NullableContext(1)] public sealed class CompanionCollector : MonoBehaviour { internal const string SelectionKey = "radamanto.companions.collect"; private const float PickableScanInterval = 2f; private const float TrackInterval = 1f; private const float TargetApproachDistance = 3.2f; private const float TargetTimeout = 20f; private const float FailedRetryDelay = 15f; private const int PickablePurgeInterval = 256; private const int MaxOverlapBuffer = 8192; private static readonly HashSet<CompanionCollector> Active = new HashSet<CompanionCollector>(); private static readonly HashSet<Pickable> Pickables = new HashSet<Pickable>(); private static readonly List<Pickable> DeadPickables = new List<Pickable>(); private static readonly Dictionary<GameObject, ItemData> Templates = new Dictionary<GameObject, ItemData>(); private static Collider[] _overlapBuffer = (Collider[])(object)new Collider[256]; private static int _itemLayerMask = -1; private static int _pickableRegistrations; private static bool _pickablesSeeded; private readonly HashSet<string> _selectedPrefabs = new HashSet<string>(); private SphereCollider _sensor = null; [<51d574fa-9559-41c7-ba50-f30c8017450e>Nullable(2)] private ZNetView _view; [<51d574fa-9559-41c7-ba50-f30c8017450e>Nullable(2)] private Inventory _inventory; [<51d574fa-9559-41c7-ba50-f30c8017450e>Nullable(2)] private CompanionIdentity _identity; private bool _started; private bool _active; private bool _collecting; private bool _scanPending; private float _pollAt = -1f; private float _trackAt = -1f; [<51d574fa-9559-41c7-ba50-f30c8017450e>Nullable(2)] private ItemDrop _targetDrop; [<51d574fa-9559-41c7-ba50-f30c8017450e>Nullable(2)] private Pickable _targetPickable; [<51d574fa-9559-41c7-ba50-f30c8017450e>Nullable(2)] private GameObject _targetAnchor; private float _targetStarted; [<51d574fa-9559-41c7-ba50-f30c8017450e>Nullable(2)] private ItemDrop _failedDrop; private float _failedUntil; [<51d574fa-9559-41c7-ba50-f30c8017450e>Nullable(2)] private Pickable _failedPickable; private float _failedPickableUntil; [<51d574fa-9559-41c7-ba50-f30c8017450e>Nullable(2)] private Player _owner; private int _ownerFrame = -1; private int _selectedFrame = -1; private float _biomeCheckAt; private bool _biomeLocked; internal static bool AnyActive => Active.Count > 0; private static CompanionCollectionMode Mode => CompanionsPlugin.CollectionMode?.Value ?? CompanionCollectionMode.MarkedItems; private static CompanionCollectionMode PickableMode => CompanionsPlugin.PickableMode?.Value ?? CompanionCollectionMode.MarkedItems; private static bool AnyModeEnabled => Mode != CompanionCollectionMode.None || PickableMode != CompanionCollectionMode.None; private static float Radius => Mathf.Clamp(CompanionsPlugin.CollectionRadius?.Value ?? 6f, 1f, 30f); private static float DetectionRadius => Mathf.Clamp(CompanionsPlugin.CollectionDetectionRadius?.Value ?? 50f, 1f, 100f); private static float PickableDetectionRadius => Mathf.Clamp(CompanionsPlugin.PickableDetectionRadius?.Value ?? 20f, 1f, 100f); private static float MaxOwnerDistance => Mathf.Clamp(CompanionsPlugin.CollectionMaxOwnerDistance?.Value ?? 70f, 10f, 150f); private static int ItemLayerMask { get { if (_itemLayerMask == -1) { int mask = LayerMask.GetMask(new string[1] { "item" }); _itemLayerMask = ((mask != 0) ? mask : (-1)); } return _itemLayerMask; } } private bool IsFollowing => (Object)(object)_view != (Object)null && _view.IsValid() && !string.IsNullOrEmpty(_view.GetZDO().GetString(ZDOVars.s_follow, "")); [<51d574fa-9559-41c7-ba50-f30c8017450e>Nullable(2)] private Player Owner { [<7664ba2c-c0fb-485d-95cb-d6607104ddd1>NullableContext(2)] get { if (_ownerFrame != Time.frameCount) { _ownerFrame = Time.frameCount; _owner = (((Object)(object)_view != (Object)null && _view.IsValid()) ? CompanionsState.FindOwner(_view.GetZDO()) : null); } return _owner; } } [<51d574fa-9559-41c7-ba50-f30c8017450e>Nullable(2)] private Transform TargetTransform { [<7664ba2c-c0fb-485d-95cb-d6607104ddd1>NullableContext(2)] get { return ((Object)(object)_targetDrop != (Object)null) ? ((Component)_targetDrop).transform : (((Object)(object)_targetPickable != (Object)null) ? ((Component)_targetPickable).transform : null); } } private void Start() { //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0089: 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_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: 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_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) _sensor = ((Component)this).GetComponent<SphereCollider>(); ApplyLayerFilter((Collider)(object)_sensor); _view = ((Component)this).GetComponentInParent<ZNetView>(); Container componentInParent = ((Component)this).GetComponentInParent<Container>(); _inventory = (((Object)(object)componentInParent != (Object)null) ? componentInParent.GetInventory() : null); if (!((Object)(object)_view == (Object)null) && _inventory != null && !((Object)(object)_sensor == (Object)null)) { Vector3 lossyScale = ((Component)this).transform.parent.lossyScale; ((Component)this).transform.localScale = new Vector3((Mathf.Abs(lossyScale.x) > 0.001f) ? (1f / Mathf.Abs(lossyScale.x)) : 1f, (Mathf.Abs(lossyScale.y) > 0.001f) ? (1f / Mathf.Abs(lossyScale.y)) : 1f, (Mathf.Abs(lossyScale.z) > 0.001f) ? (1f / Mathf.Abs(lossyScale.z)) : 1f); Inventory inventory = _inventory; inventory.m_onChanged = (Action)Delegate.Combine(inventory.m_onChanged, new Action(OnInventoryChanged)); ((Collider)_sensor).enabled = false; _started = true; UpdateActive(); } } private void Update() { if (!_active) { return; } float time = Time.time; if (time >= _biomeCheckAt) { _biomeCheckAt = time + 1f; bool flag = IsOwnerBiomeLocked(); if (flag != _biomeLocked) { _biomeLocked = flag; if (!flag) { ScheduleScan(); } } } if (_trackAt >= 0f && time >= _trackAt) { _trackAt = time + 1f; TrackTarget(); } if (_pollAt >= 0f && time >= _pollAt) { _pollAt = time + 2f; if ((Object)(object)_targetDrop == (Object)null && (Object)(object)_targetPickable == (Object)null) { ScanNearby(); } } if (_scanPending) { _scanPending = false; ScanNearby(); } } private void OnDestroy() { CancelTarget(); if ((Object)(object)_targetAnchor != (Object)null) { Object.Destroy((Object)(object)_targetAnchor); } _targetAnchor = null; if (_active) { _active = false; RemoveActive(); } if (_inventory != null) { Inventory inventory = _inventory; inventory.m_onChanged = (Action)Delegate.Remove(inventory.m_onChanged, new Action(OnInventoryChanged)); } } private void OnTriggerEnter(Collider other) { if (_active) { ItemDrop componentInParent = ((Component)other).GetComponentInParent<ItemDrop>(); if ((Object)(object)componentInParent != (Object)null) { ScheduleScan(); } } } private void OnInventoryChanged() { _selectedFrame = -1; if (!_collecting) { ScheduleScan(); } } private void Deactivate() { RemoveActive(); CancelTarget(); _scanPending = false; _pollAt = -1f; if ((Object)(object)_sensor != (Object)null) { ((Collider)_sensor).enabled = false; } } private void RemoveActive() { Active.Remove(this); if (Active.Count == 0) { ReleasePickables(); } } private bool CanCollect() { return _active && AnyModeEnabled && IsFollowing && (Object)(object)_view != (Object)null && _view.IsValid() && _view.IsOwner() && _inventory != null && !CompanionWeight.IsOverweight(_view.GetZDO()) && !_view.GetZDO().GetBool(CompanionsFlight.DungeonWaitKey, false) && !IsOwnerBiomeLocked(); } private bool IsOwnerBiomeLocked() { Player owner = Owner; if ((Object)(object)owner == (Object)null || (Object)(object)owner != (Object)(object)Player.m_localPlayer) { return false; } return CompanionsBiomeLock.IsRestricted(); } private void SetCollecting(bool collecting) { if ((Object)(object)_identity == (Object)null && (Object)(object)_view != (Object)null) { _identity = ((Component)_view).GetComponent<CompanionIdentity>(); } if ((Object)(object)_identity != (Object)null) { _identity.Collecting = collecting; } } private bool TargetStillValid() { int capacity; if ((Object)(object)_targetDrop != (Object)null) { return CanTake(_targetDrop, out capacity); } if ((Object)(object)_targetPickable != (Object)null) { return CanHarvest(_targetPickable); } return false; } [<7664ba2c-c0fb-485d-95cb-d6607104ddd1>NullableContext(2)] private void StartTarget(ItemDrop drop, Pickable pickable) { //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Expected O, but got Unknown if (!IsFollowing || IsOwnerTooFar() || (Object)(object)_view == (Object)null || ((Object)(object)drop == (Object)null && (Object)(object)pickable == (Object)null)) { return; } Character component = ((Component)_view).GetComponent<Character>(); if (!((Object)(object)component == (Object)null)) { CancelTarget(); _targetDrop = drop; _targetPickable = pickable; if ((Object)(object)_targetAnchor == (Object)null) { _targetAnchor = new GameObject("CompanionCollectionTarget"); } SetCollecting(collecting: true); _targetStarted = Time.time; UpdateTargetPosition(); CompanionsFlight.FollowCollectionTarget(component, _targetAnchor); _trackAt = Time.time + 1f; } } private void UpdateTargetPosition() { //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_0047: 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_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: 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_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) Transform targetTransform = TargetTransform; if (!((Object)(object)targetTransform == (Object)null) && !((Object)(object)_targetAnchor == (Object)null) && !((Object)(object)_view == (Object)null)) { Vector3 val = targetTransform.position + Vector3.up * CompanionsFlight.Height; Vector3 val2 = targetTransform.position - ((Component)_view).transform.position; val2.y = 0f; if (((Vector3)(ref val2)).sqrMagnitude > 0.01f) { val += ((Vector3)(ref val2)).normalized * Mathf.Max(0f, 3.2f - Radius); } _targetAnchor.transform.position = val; } } private void TrackTarget() { //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) Transform targetTransform = TargetTransform; if ((Object)(object)targetTransform == (Object)null || (Object)(object)_targetAnchor == (Object)null || !IsFollowing || IsOwnerTooFar() || !TargetStillValid()) { FinishTarget(); } else if (Time.time - _targetStarted > 20f) { if ((Object)(object)_targetDrop != (Object)null) { _failedDrop = _targetDrop; _failedUntil = Time.time + 15f; } else { _failedPickable = _targetPickable; _failedPickableUntil = Time.time + 15f; } FinishTarget(); } else { Vector3 val = ((Component)_view).transform.position - targetTransform.position; if (((Vector3)(ref val)).sqrMagnitude <= Radius * Radius && (((Object)(object)_targetDrop != (Object)null) ? TryCollect(_targetDrop) : TryHarvest(_targetPickable))) { FinishTarget(); } else { UpdateTargetPosition(); } } } private void FinishTarget() { CancelTarget(); ScanNearby(); if ((Object)(object)_targetDrop == (Object)null && (Object)(object)_targetPickable == (Object)null && (Object)(object)_view != (Object)null) { CompanionsFlight.RestoreFollow(((Component)_view).gameObject, smooth: true); ScheduleScan(); } } internal static void RegisterPickable(Pickable pickable) { if (_pickablesSeeded && !((Object)(object)pickable == (Object)null)) { Pickables.Add(pickable); if (++_pickableRegistrations % 256 == 0) { PurgeDeadPickables(); } } } [<7664ba2c-c0fb-485d-95cb-d6607104ddd1>NullableContext(2)] internal static void ApplyLayerFilter(Collider trigger) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)trigger == (Object)null)) { int itemLayerMask = ItemLayerMask; trigger.excludeLayers = LayerMask.op_Implicit((itemLayerMask != -1) ? (~itemLayerMask) : 0); } } [<7664ba2c-c0fb-485d-95cb-d6607104ddd1>NullableContext(2)] internal static bool IsSelected(ItemData item) { return item?.m_customData.ContainsKey("radamanto.companions.collect") ?? false; } internal static void RefreshSensors() { foreach (CompanionCollector item in Active) { item.RefreshSensor(); } } internal static void NotifyNearby(ItemDrop drop) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_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_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)drop == (Object)null) { return; } float num = Mathf.Max(Radius, DetectionRadius); float num2 = num * num; Vector3 position = ((Component)drop).transform.position; foreach (CompanionCollector item in Active) { if ((Object)(object)item != (Object)null) { Vector3 val = ((Component)item).transform.position - position; if (((Vector3)(ref val)).sqrMagnitude <= num2) { item.ScheduleScan(); } } } } internal static void ResetStatics() { Active.Clear(); ReleasePickables(); Templates.Clear(); } internal void ScheduleScan() { _scanPending = true; } internal void UpdateActive() { if (!_started) { return; } bool flag = (Object)(object)_view != (Object)null && _view.IsValid() && _view.IsOwner(); if (flag == _active) { if (flag) { ScheduleScan(); } return; } _active = flag; if (flag) { Active.Add(this); RefreshSensor(); ScheduleScan(); } else { Deactivate(); } } internal void CancelTarget() { _trackAt = -1f; _targetDrop = null; _targetPickable = null; SetCollecting(collecting: false); } internal bool RestoreTarget(Character character) { if (((Object)(object)_targetDrop == (Object)null && (Object)(object)_targetPickable == (Object)null) || (Object)(object)_targetAnchor == (Object)null) { return false; } if (!IsFollowing || IsOwnerTooFar() || !TargetStillValid()) { CancelTarget(); return false; } UpdateTargetPosition(); CompanionsFlight.FollowCollectionTarget(character, _targetAnchor); return true; } private static void PurgeDeadPickables() { foreach (Pickable pickable in Pickables) { if ((Object)(object)pickable == (Object)null) { DeadPickables.Add(pickable); } } for (int i = 0; i < DeadPickables.Count; i++) { Pickables.Remove(DeadPickables[i]); } DeadPickables.Clear(); } private static void SeedPickables() { if (!_pickablesSeeded) { _pickablesSeeded = true; Pickables.Clear(); Pickable[] array = Object.FindObjectsByType<Pickable>((FindObjectsSortMode)0); foreach (Pickable item in array) { Pickables.Add(item); } } } private static void ReleasePickables() { _pickablesSeeded = false; _pickableRegistrations = 0; Pickables.Clear(); DeadPickables.Clear(); } private static bool IsWardProtected(Vector3 point, long ownerId) { //IL_003e: 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) List<PrivateArea> allAreas = PrivateArea.m_allAreas; if (allAreas == null) { return false; } foreach (PrivateArea item in allAreas) { if (!((Object)(object)item == (Object)null) && !(Utils.DistanceXZ(((Component)item).transform.position, point) >= item.m_radius)) { ZNetView nview = item.m_nview; Piece piece = item.m_piece; if ((Object)(object)nview != (Object)null && nview.IsValid() && nview.GetZDO().GetBool(ZDOVars.s_enabled, false) && (ownerId == 0L || (Object)(object)piece == (Object)null || piece.GetCreator() != ownerId)) { return true; } } } return false; } private static int OverlapItems(Vector3 position, float radius) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) int num; while (true) { num = Physics.OverlapSphereNonAlloc(position, radius, _overlapBuffer, ItemLayerMask, (QueryTriggerInteraction)2); if (num < _overlapBuffer.Length || _overlapBuffer.Length >= 8192) { break; } _overlapBuffer = (Collider[])(object)new Collider[_overlapBuffer.Length * 2]; } return num; } private void RefreshSensor() { if ((Object)(object)_sensor == (Object)null) { return; } _sensor.radius = Mathf.Max(Radius, DetectionRadius); ((Collider)_sensor).enabled = _active && Mode != CompanionCollectionMode.None; _pollAt = ((_active && PickableMode != CompanionCollectionMode.None) ? (Time.time + Random.Range(0.5f, 2f)) : (-1f)); if ((!((Object)(object)_targetDrop != (Object)null) || Mode == CompanionCollectionMode.None) && (!((Object)(object)_targetPickable != (Object)null) || PickableMode == CompanionCollectionMode.None) && ((Object)(object)_targetDrop != (Object)null || (Object)(object)_targetPickable != (Object)null)) { CancelTarget(); if ((Object)(object)_view != (Object)null) { CompanionsFlight.RestoreFollow(((Component)_view).gameObject); } } if (AnyModeEnabled) { ScanNearby(); } } private bool IsOwnerTooFar() { //IL_0017: 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) Player owner = Owner; return (Object)(object)owner == (Object)null || Utils.DistanceXZ(((Component)owner).transform.position, ((Component)this).transform.position) > MaxOwnerDistance; } private bool IsBeyondOwnerRange(Vector3 point) { //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) Player owner = Owner; return owner == null || Utils.DistanceXZ(((Component)owner).transform.position, point) > MaxOwnerDistance; } private void ScanNearby() { if (!_collecting && CanCollect()) { if ((Object)(object)_targetDrop != (Object)null || (Object)(object)_targetPickable != (Object)null) { TrackTarget(); } else if (!IsOwnerTooFar() && !ScanDrops()) { ScanPickables(); } } } private bool ScanDrops() { //IL_0035: 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_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) if (Mode == CompanionCollectionMode.None) { return false; } float radius = Mathf.Max(Radius, DetectionRadius); ItemDrop val = null; float num = float.MaxValue; int num2 = OverlapItems(((Component)this).transform.position, radius); for (int i = 0; i < num2; i++) { Collider val2 = _overlapBuffer[i]; _overlapBuffer[i] = null; if ((Object)(object)val2 == (Object)null) { continue; } ItemDrop componentInParent = ((Component)val2).GetComponentInParent<ItemDrop>(); if (!((Object)(object)componentInParent == (Object)null) && (!((Object)(object)componentInParent == (Object)(object)_failedDrop) || !(Time.time < _failedUntil)) && CanTake(componentInParent, out var _)) { Vector3 val3 = ((Component)this).transform.position - ((Component)componentInParent).transform.position; float sqrMagnitude = ((Vector3)(ref val3)).sqrMagnitude; if (sqrMagnitude < num) { val = componentInParent; num = sqrMagnitude; } } } if ((Object)(object)val == (Object)null) { return false; } if (num <= Radius * Radius && TryCollect(val)) { ScheduleScan(); return true; } StartTarget(val, null); return true; } private void ScanPickables() { //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_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009d: 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) if (PickableMode == CompanionCollectionMode.None) { return; } SeedPickables(); if (Pickables.Count == 0) { return; } float num = Mathf.Max(Radius, PickableDetectionRadius); float num2 = num * num; Vector3 position = ((Component)this).transform.position; Pickable val = null; float num3 = float.MaxValue; foreach (Pickable pickable in Pickables) { if ((Object)(object)pickable == (Object)null) { DeadPickables.Add(pickable); continue; } Vector3 val2 = position - ((Component)pickable).transform.position; float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude; if (!(sqrMagnitude > num2) && !(sqrMagnitude >= num3) && (!((Object)(object)pickable == (Object)(object)_failedPickable) || !(Time.time < _failedPickableUntil)) && CanHarvest(pickable)) { val = pickable; num3 = sqrMagnitude; } } if (DeadPickables.Count > 0) { for (int i = 0; i < DeadPickables.Count; i++) { Pickables.Remove(DeadPickables[i]); } DeadPickables.Clear(); } if (!((Object)(object)val == (Object)null)) { if (num3 <= Radius * Radius && TryHarvest(val)) { ScheduleScan(); } else { StartTarget(null, val); } } } [<7664ba2c-c0fb-485d-95cb-d6607104ddd1>NullableContext(2)] private static ItemData GetTemplate(GameObject prefab) { if ((Object)(object)prefab == (Object)null) { return null; } if (Templates.TryGetValue(prefab, out var value)) { return value; } ItemData val = CreateItem(prefab, 1); if (val != null) { Templates[prefab] = val; } return val; } [<7664ba2c-c0fb-485d-95cb-d6607104ddd1>NullableContext(2)] private static ItemData CreateItem(GameObject prefab, int stack) { ItemDrop val = (((Object)(object)prefab != (Object)null) ? prefab.GetComponent<ItemDrop>() : null); if ((Object)(object)val == (Object)null || val.m_itemData == null) { return null; } ItemData val2 = val.m_itemData.Clone(); val2.m_dropPrefab = prefab; val2.m_stack = stack; val2.m_worldLevel = (byte)Game.m_worldLevel; return val2; } private static int HarvestAmount(Pickable pickable) { return pickable.m_dontScale ? pickable.m_amount : Mathf.Max(pickable.m_minAmountScaled, Game.instance.ScaleDrops(pickable.m_itemPrefab, pickable.m_amount)); } private bool CanHarvest(Pickable pickable) { //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0119: 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_0143: Unknown result type (might be due to invalid IL or missing references) if (PickableMode == CompanionCollectionMode.None || !CanCollect() || (Object)(object)pickable == (Object)null || (Object)(object)pickable.m_itemPrefab == (Object)null) { return false; } ZNetView nview = pickable.m_nview; if ((Object)(object)nview == (Object)null || !nview.IsValid() || pickable.GetPicked() || pickable.GetEnabled != 1 || IsControlledByOtherPeer(nview.GetZDO())) { return false; } if (pickable.m_tarPreventsPicking) { Floating component = ((Component)pickable).GetComponent<Floating>(); if ((Object)(object)component != (Object)null && component.IsInTar()) { return false; } } CompanionCollectionMode pickableMode = PickableMode; if (pickableMode == CompanionCollectionMode.MarkedItems && !IsPrefabSelected(Utils.GetPrefabName(pickable.m_itemPrefab))) { return false; } ItemData template = GetTemplate(pickable.m_itemPrefab); if (template == null || CompanionsContainer.IsBlocked(_inventory, template)) { return false; } Vector3 position = ((Component)pickable).transform.position; if (IsWardProtected(position, _view.GetZDO().GetLong(CompanionsState.OwnerKey, 0L))) { return false; } if (IsBeyondOwnerRange(position)) { return false; } int num = FreeCapacity(template); int num2 = Mathf.Max(1, pickable.m_amount); if (!CanCarry(template, Mathf.Min(num2, num))) { return false; } return (pickableMode == CompanionCollectionMode.MarkedItems) ? (num > 0) : (num >= Mathf.Max(1, pickable.m_amount)); } private static bool IsControlledByOtherPeer(ZDO zdo) { long owner = zdo.GetOwner(); return owner != 0L && owner != ZDOMan.GetSessionID(); } private bool TryHarvest(Pickable pickable) { //IL_0018: 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) //IL_0028: 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_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: 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_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_01c4: Unknown result type (might be due to invalid IL or missing references) if (!_collecting && CanHarvest(pickable)) { Vector3 val = ((Component)this).transform.position - ((Component)pickable).transform.position; if (!(((Vector3)(ref val)).sqrMagnitude > Radius * Radius) && !IsOwnerTooFar()) { int num = HarvestAmount(pickable); ItemData template = GetTemplate(pickable.m_itemPrefab); if (template == null || !CanCarry(template, Mathf.Min(num, FreeCapacity(template)))) { return false; } ZNetView nview = pickable.m_nview; nview.ClaimOwnership(); if (!nview.IsOwner() || pickable.GetPicked()) { return false; } _collecting = true; try { Vector3 val2 = (pickable.m_pickEffectAtSpawnPoint ? (((Component)pickable).transform.position + pickable.GetSpawnOffset()) : ((Component)pickable).transform.position); pickable.m_pickEffector.Create(val2, Quaternion.identity, (Transform)null, 1f, -1, default(ZDOID)); StoreOrDrop(pickable, pickable.m_itemPrefab, num); if (!pickable.m_extraDrops.IsEmpty()) { foreach (ItemData dropListItem in pickable.m_extraDrops.GetDropListItems()) { if (dropListItem != null && (Object)(object)dropListItem.m_dropPrefab != (Object)null) { StoreOrDrop(pickable, dropListItem.m_dropPrefab, dropListItem.m_stack); } } } if (pickable.m_aggravateRange > 0f) { BaseAI.AggravateAllInArea(((Component)pickable).transform.position, pickable.m_aggravateRange, (AggravatedReason)2); } nview.InvokeRPC(ZNetView.Everybody, "RPC_SetPicked", new object[1] { true }); return true; } finally { _collecting = false; } } } return false; } private void StoreOrDrop(Pickable pickable, GameObject prefab, int amount) { ItemData template = GetTemplate(prefab); if (template == null || amount <= 0) { return; } bool flag = CompanionsContainer.IsBlocked(_inventory, template); int num = amount; while (!flag && num > 0) { int num2 = Mathf.Min(new int[3] { num, template.m_shared.m_maxStackSize, FreeCapacity(template) }); if (num2 <= 0) { break; } ItemData val = CreateItem(prefab, num2); if (val == null || !CanCarry(val, num2) || !_inventory.AddItem(val)) { break; } num -= num2; } int num3 = 0; while (num > 0) { int num4 = Mathf.Min(num, template.m_shared.m_maxStackSize); pickable.Drop(prefab, num3++, num4); num -= num4; } } private bool CanTake(ItemDrop drop, out int capacity) { //IL_005c: 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) capacity = 0; if (Mode == CompanionCollectionMode.None || !CanCollect() || (Object)(object)drop == (Object)null || IsWardProtected(((Component)drop).transform.position, _view.GetZDO().GetLong(CompanionsState.OwnerKey, 0L))) { return false; } if (IsBeyondOwnerRange(((Component)drop).transform.position)) { return false; } ZNetView nview = drop.m_nview; if ((Object)(object)nview == (Object)null || !nview.IsValid()) { return false; } drop.Load(); ItemData itemData = drop.m_itemData; if (itemData == null || (Object)(object)itemData.m_dropPrefab == (Object)null || itemData.m_stack <= 0 || !IsOwnDrop(nview.GetZDO(), itemData) || CompanionsContainer.IsBlocked(_inventory, itemData)) { return false; } CompanionCollectionMode mode = Mode; string prefabName = Utils.GetPrefabName(itemData.m_dropPrefab); if (mode == CompanionCollectionMode.MarkedItems && !IsPrefabSelected(prefabName)) { return false; } int num = 0; foreach (ItemData allItem in _inventory.GetAllItems()) { if (allItem.IsSameType(itemData)) { num += Mathf.Max(0, allItem.m_shared.m_maxStackSize - allItem.m_stack); } } int num2 = _inventory.GetEmptySlots() * itemData.m_shared.m_maxStackSize; capacity = num + num2; int amount = ((mode == CompanionCollectionMode.MarkedItems) ? Mathf.Min(itemData.m_stack, capacity) : itemData.m_stack); if (!CanCarry(itemData, amount)) { return false; } return (mode == CompanionCollectionMode.MarkedItems) ? (capacity > 0) : (capacity >= itemData.m_stack); } private bool IsOwnDrop(ZDO dropZdo, ItemData item) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) if (!item.m_pickedUp) { return true; } long userID = ((ZDOID)(ref dropZdo.m_uid)).UserID; if (userID == ZDOID.NullUser || userID == ZDOID.UnknownFormerUser) { return true; } Player owner = Owner; int result; if ((Object)(object)owner != (Object)null) { ZDOID zDOID = ((Character)owner).GetZDOID(); result = ((userID == ((ZDOID)(ref zDOID)).UserID) ? 1 : 0); } else { result = 0; } return (byte)result != 0; } private bool IsPrefabSelected(string prefabName) { if (_selectedFrame != Time.frameCount) { _selectedFrame = Time.frameCount; _selectedPrefabs.Clear(); foreach (ItemData allItem in _inventory.GetAllItems()) { if (IsSelected(allItem) && (Object)(object)allItem.m_dropPrefab != (Object)null) { _selectedPrefabs.Add(Utils.GetPrefabName(allItem.m_dropPrefab)); } } } return _selectedPrefabs.Contains(prefabName); } private int FreeCapacity(ItemData item) { return _inventory.FindFreeStackSpace(item.m_shared.m_name, (float)Game.m_worldLevel) + _inventory.GetEmptySlots() * item.m_shared.m_maxStackSize; } private bool CanCarry(ItemData item, int amount) { if (!CompanionWeight.Enabled) { return true; } CompanionDefinition companionDefinition = CompanionsRegistry.ForCompanion(_view.GetZDO()); return companionDefinition == null || _inventory.GetTotalWeight() + item.GetWeight(amount) < companionDefinition.MaxCarryWeight; } private bool TryCollect(ItemDrop drop) { //IL_001a: 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_002f: Unknown result type (might be due to invalid IL or missing references) if (!_collecting && CanTake(drop, out var capacity)) { Vector3 val = ((Component)this).transform.position - ((Component)drop).transform.position; if (!(((Vector3)(ref val)).sqrMagnitude > Radius * Radius) && !IsOwnerTooFar()) { ZNetView nview = drop.m_nview; if (!drop.CanPickup(false)) { drop.RequestOwn(); return false; } _collecting = true; try { ItemData itemData = drop.m_itemData; ItemData val2 = itemData.Clone(); int num = (val2.m_stack = ((Mode == CompanionCollectionMode.MarkedItems) ? Mathf.Min(itemData.m_stack, capacity) : itemData.m_stack)); val2.m_customData.Remove("radamanto.companions.collect"); if (!CanCarry(val2, num)) { return false; } bool flag = _inventory.AddItem(val2); if (flag && nview.IsOwner()) { if (num == itemData.m_stack) { nview.Destroy(); } else { itemData.m_stack -= num; ItemDrop.SaveToZDO(itemData, nview.GetZDO(), -1); } } return flag; } finally { _collecting = false; } } } return false; } } [<7664ba2c-c0fb-485d-95cb-d6607104ddd1>NullableContext(1)] [<51d574fa-9559-41c7-ba50-f30c8017450e>Nullable(0)] internal static class CompanionsCollectionSelection { private const string OverlayName = "CompanionCollectionSelection"; private const string TooltipKeyColor = "#ADFF2F"; private const string TooltipTextColor = "#FFD700"; private static readonly Color SelectedColor = new Color(0.15f, 0.85f, 0.25f, 0.38f); private static readonly HashSet<string> SelectedPrefabs = new HashSet<string>(); [<51d574fa-9559-41c7-ba50-f30c8017450e>Nullable(2)] private static Container _container; [<51d574fa-9559-41c7-ba50-f30c8017450e>Nullable(2)] private static Inventory _inventory; [<51d574fa-9559-41c7-ba50-f30c8017450e>Nullable(2)] private static InventoryGrid _grid; private static bool _normalizing; internal static void Open(InventoryGui gui, Container container) { Close(); if ((Object)(object)gui == (Object)null || (Object)(object)container == (Object)null || !CompanionsContainer.IsCompanionContainer(container) || !CompanionsState.IsOwner((Humanoid)(object)Player.m_localPlayer, CompanionsContainer.GetView((Component)(object)container))) { return; } _container = container; _inventory = container.GetInventory(); _grid = gui.ContainerGrid; if (_inventory == null || (Object)(object)_grid == (Object)null) { Close(); return; } if (_grid.m_elements.Count == 0) { _grid.m_width = 0; _grid.m_height = 0; } NormalizeSelection(); Inventory inventory = _inventory; inventory.m_onChanged = (Action)Delegate.Combine(inventory.m_onChanged, new Action(Refresh)); Refresh(); } internal static void Close() { if (_inventory != null) { Inventory inventory = _inventory; inventory.m_onChanged = (Action)Delegate.Remove(inventory.m_onChanged, new Action(Refresh)); } if ((Object)(object)_grid != (Object)null) { InventoryElement[] componentsInChildren = ((Component)_grid.m_gridRoot).GetComponentsInChildren<InventoryElement>(true); foreach (InventoryElement element in componentsInChildren) { SetMark(element, selected: false); } } _container = null; _inventory = null; _grid = null; } internal static bool OnLeftDown(InventoryGrid grid, UIInputHandler handler) { //IL_0059: 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) if ((Object)(object)_grid != (Object)(object)grid || (Object)(object)_container == (Object)null || _inventory == null || !CompanionsControls.IsSelectModifierHeld()) { return true; } InventoryElement componentInParent = ((Component)handler).GetComponentInParent<InventoryElement>(); if ((Object)(object)componentInParent == (Object)null) { return false; } ItemData itemAt = _inventory.GetItemAt(componentInParent.Position.x, componentInParent.Position.y); if (itemAt == null) { return false; } if (!_container.IsOwner()) { return false; } if (CompanionsContainer.IsBlocked(_inventory, itemAt)) { CompanionsContainer.Show("$companions_msg_blocked_item"); return false; } if ((Object)(object)itemAt.m_dropPrefab == (Object)null) { return false; } if (CompanionCollector.IsSelected(itemAt)) { itemAt.m_customData.Remove("radamanto.companions.collect"); } else { string prefabName = Utils.GetPrefabName(itemAt.m_dropPrefab); foreach (ItemData allItem in _inventory.GetAllItems()) { if ((Object)(object)allItem.m_dropPrefab != (Object)null && Utils.GetPrefabName(allItem.m_dropPrefab) == prefabName) { allItem.m_customData.Remove("radamanto.companions.collect"); } } itemAt.m_customData["radamanto.companions.collect"] = "1"; } _inventory.m_onChanged?.Invoke(); return false; } internal static void OnElementInitialized(InventoryElement element) { if ((Object)(object)_grid != (Object)null && (Object)(object)((Component)element).GetComponentInParent<InventoryGrid>() == (Object)(object)_grid) { UpdateMark(element); } } internal static void AppendItemTooltip(InventoryGrid grid, ItemData item, UITooltip tooltip) { //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)grid != (Object)(object)_grid) && _inventory != null && item != null && !((Object)(object)tooltip == (Object)null)) { string text = CompanionsLocalization.Localize("$companions_tooltip_click").Replace("{0}", CompanionsControls.SelectModifierLabel); string text2 = CompanionsLocalization.Localize(CompanionCollector.IsSelected(item) ? "$companions_tooltip_deselect_collection" : "$companions_tooltip_select_collection"); string text3 = "<color=#FFD700><b>" + text2.Replace("{0}", "<color=#ADFF2F>" + text + "</color>") + "</b></color>"; tooltip.Set(tooltip.m_topic, tooltip.m_text + "\n\n" + text3, grid.m_tooltipAnchor, default(Vector2)); } } private static bool NormalizeSelection() { if (_inventory == null || _normalizing) { return false; } SelectedPrefabs.Clear(); bool flag = false; foreach (ItemData allItem in _inventory.GetAllItems()) { if (CompanionCollector.IsSelected(allItem) && ((Object)(object)allItem.m_dropPrefab == (Object)null || !SelectedPrefabs.Add(Utils.GetPrefabName(allItem.m_dropPrefab)))) { allItem.m_customData.Remove("radamanto.companions.collect"); flag = true; } } if (!flag) { return false; } _normalizing = true; try { _inventory.m_onChanged?.Invoke(); } finally { _normalizing = false; } return true; } private static void Refresh() { if (!((Object)(object)_grid == (Object)null) && _inventory != null && !NormalizeSelection()) { InventoryElement[] componentsInChildren = ((Component)_grid.m_gridRoot).GetComponentsInChildren<InventoryElement>(true); foreach (InventoryElement element in componentsInChildren) { UpdateMark(element); } } } private static void UpdateMark(InventoryElement element) { //IL_000e: 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) Inventory inventory = _inventory; ItemData item = ((inventory != null) ? inventory.GetItemAt(element.Position.x, element.Position.y) : null); SetMark(element, CompanionCollector.IsSelected(item)); } private static void SetMark(InventoryElement element, bool selected) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Expected O, but got Unknown //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Expected O, but got Unknown //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0086: 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_00a7: Unknown result type (might be due to invalid IL or missing references) Transform val = ((Component)element).transform.Find("CompanionCollectionSelection"); if ((Object)(object)val == (Object)null && selected) { GameObject val2 = new GameObject("CompanionCollectionSelection", new Type[2] { typeof(RectTransform), typeof(Image) }); val2.transform.SetParent(((Component)element).transform, false); RectTransform val3 = (RectTransform)val2.transform; val3.anchorMin = Vector2.zero; val3.anchorMax = Vector2.one; val3.offsetMin = Vector2.zero; val3.offsetMax = Vector2.zero; Image component = val2.GetComponent<Image>(); ((Graphic)component).color = SelectedColor; ((Graphic)component).raycastTarget = false; val2.transform.SetAsFirstSibling(); val = val2.transform; } if ((Object)(object)val != (Object)null) { ((Component)val).gameObject.SetActive(selected); } } } [HarmonyPatch(typeof(InventoryGui), "Show", new Type[] { typeof(Container), typeof(int) })] internal static class InventoryGui_Show_CompanionSelection_Patch { [<7664ba2c-c0fb-485d-95cb-d6607104ddd1>NullableContext(1)] private static void Postfix(InventoryGui __instance, Container container) { CompanionsCollectionSelection.Open(__instance, container); } } [HarmonyPatch(typeof(InventoryGui), "Hide")] internal static class InventoryGui_Hide_CompanionSelection_Patch { private static void Prefix() { CompanionsCollectionSelection.Close(); } } [HarmonyPatch(typeof(InventoryGui), "CloseContainer")] internal static class InventoryGui_CloseContainer_CompanionSelection_Patch { private static void Prefix() { CompanionsCollectionSelection.Close(); } } [HarmonyPatch(typeof(InventoryGrid), "OnLeftDown", new Type[] { typeof(UIInputHandler) })] internal static class InventoryGrid_OnLeftDown_CompanionSelection_Patch { [<7664ba2c-c0fb-485d-95cb-d6607104ddd1>NullableContext(1)] private static bool Prefix(InventoryGrid __instance, UIInputHandler clickHandler) { return CompanionsCollectionSelection.OnLeftDown(__instance, clickHandler); } } [HarmonyPatch(typeof(InventoryElement), "Initialize", new Type[] { typeof(int), typeof(int) })] internal static class InventoryElement_Initialize_CompanionSelection_Patch { [<7664ba2c-c0fb-485d-95cb-d6607104ddd1>NullableContext(1)] private static void Postfix(InventoryElement __instance) { CompanionsCollectionSelection.OnElementInitialized(__instance); } } [HarmonyPatch(typeof(InventoryGrid), "CreateItemTooltip", new Type[] { typeof(ItemData), typeof(UITooltip) })] internal static class InventoryGrid_CreateItemTooltip_CompanionSelection_Patch { [<7664ba2c-c0fb-485d-95cb-d6607104ddd1>NullableContext(1)] private static void Postfix(InventoryGrid __instance, ItemData item, UITooltip tooltip) { CompanionsCollectionSelection.AppendItemTooltip(__instance, item, tooltip); } } [<51d574fa-9559-41c7-ba50-f30c8017450e>Nullable(0)] [<7664ba2c-c0fb-485d-95cb-d6607104ddd1>NullableContext(1)] internal static class CompanionsAudio { private static readonly HashSet<AudioSource> Sources = new HashSet<AudioSource>(); [<51d574fa-9559-41c7-ba50-f30c8017450e>Nullable(2)] private static AudioMixer _appliedMixer; internal static void Initialize(AssetBundle bundle) { if (Application.isBatchMode || (Object)(object)bundle == (Object)null) { return; } Sources.Clear(); GameObject[] array = bundle.LoadAllAssets<GameObject>(); foreach (GameObject val in array) { if ((Object)(object)val == (Object)null) { continue; } AudioSource[] componentsInChildren = val.GetComponentsInChildren<AudioSource>(true); foreach (AudioSource val2 in componentsInChildren) { if ((Object)(object)val2 != (Object)null) { Sources.Add(val2); } } } Apply(AudioMan.instance); } [<7664ba2c-c0fb-485d-95cb-d6607104ddd1>NullableContext(2)] internal static void Apply(AudioMan audioManager) { AudioMixer val = (((Object)(object)audioManager != (Object)null) ? audioManager.m_masterMixer : null); if ((Object)(object)val == (Object)null || (Object)(object)val == (Object)(object)_appliedMixer) { return; } AudioMixerGroup val2 = FindSfx(val); if ((Object)(object)val2 == (Object)null) { return; } foreach (AudioSource source in Sources) { if ((Object)(object)source != (Object)null) { source.outputAudioMixerGroup = val2; } } _appliedMixer = val; } [return: <51d574fa-9559-41c7-ba50-f30c8017450e>Nullable(2)] private static AudioMixerGroup FindSfx(AudioMixer mixer) { AudioMixerGroup[] array = mixer.FindMatchingGroups(string.Empty); foreach (AudioMixerGroup val in array) { if ((Object)(object)val != (Object)null && string.Equals(((Object)val).name, "SFX", StringComparison.OrdinalIgnoreCase)) { return val; } } return null; } } [HarmonyPatch(typeof(AudioMan), "Awake")] internal static class AudioMan_Awake_CompanionAudio_Patch { [<7664ba2c-c0fb-485d-95cb-d6607104ddd1>NullableContext(1)] private static void Postfix(AudioMan __instance) { CompanionsAudio.Apply(__instance); } } internal static class CompanionsDefaults { internal const CompanionCollectionMode CollectionMode = CompanionCollectionMode.MarkedItems; internal const float PickupRadius = 6f; internal const float MinPickupRadius = 1f; internal const float MaxPickupRadius = 30f; internal const float DropDetectionRadius = 50f; internal const float PickableDetectionRadius = 20f; internal const float MinDetectionRadius = 1f; internal const float MaxDetectionRadius = 100f; internal const float MaxOwnerDistance = 70f; internal const float MinOwnerDistance = 10f; internal const float MaxMaxOwnerDistance = 150f; internal const bool TeleportCompanion = true; internal const bool WaitAtDungeonEntrance = false; internal const bool CatchUpTeleport = true; internal const float CatchUpDistance = 80f; internal const bool ShowMapIcon = true; internal const CompanionSelectModifier SelectModifier = CompanionSelectModifier.Alt; internal static readonly KeyboardShortcut CallKey = new KeyboardShortcut((KeyCode)104, Array.Empty<KeyCode>()); internal static readonly KeyboardShortcut FollowStayKey = new KeyboardShortcut((KeyCode)101, Array.Empty<KeyCode>()); internal static readonly KeyboardShortcut OpenChestKey = new KeyboardShortcut((KeyCode)101, (KeyCode[])(object)new KeyCode[1] { (KeyCode)304 }); } [<51d574fa-9559-41c7-ba50-f30c8017450e>Nullable(0)] [<7664ba2c-c0fb-485d-95cb-d6607104ddd1>NullableContext(1)] internal static class CompanionTokens { internal const string DragonNestName = "$companions_piece_dragon_nest_name"; internal const string DragonNestDescription = "$companions_piece_dragon_nest_description"; internal const string SlotName = "$companions_slot_name"; internal const string ChestName = "$companions_chest_name"; internal const string CargoName = "$companions_cargo_name"; internal const string HoverFollowStay = "$companions_hover_follow_stay"; internal const string HoverOpenChest = "$companions_hover_open_chest"; internal const string HoverCall = "$companions_hover_call"; internal const string TooltipClick = "$companions_tooltip_click"; internal const string TooltipSelectCollection = "$companions_tooltip_select_collection"; internal const string TooltipDeselectCollection = "$companions_tooltip_deselect_collection"; internal const string PopupTitle = "$companions_popup_title"; internal const string PopupDiscard = "$companions_popup_discard"; internal const string MsgPopupUnavailable = "$companions_msg_popup_unavailable"; internal const string MsgOverweight = "$companions_msg_overweight"; internal const string MsgBlockedItem = "$companions_msg_blocked_item"; internal const string MsgOwnerOpen = "$companions_msg_owner_open"; internal const string MsgOwnerTakeAll = "$companions_msg_owner_take_all"; internal const string MsgUnequipFirst = "$companions_msg_unequip_first"; internal const string MsgWaitingAtEntrance = "$companions_msg_waiting_at_entrance"; internal const string MsgCalled = "$companions_msg_called"; internal const string MsgServerUnavailable = "$companions_msg_server_unavailable"; internal const string MsgServerNotResponding = "$companions_msg_server_not_responding"; } internal static class CompanionsLocalization { [<7664ba2c-c0fb-485d-95cb-d6607104ddd1>NullableContext(1)] internal static string Localize(string token) { if (Localization.instance == null) { return token; } string text = Localization.instance.Localize(token); return string.IsNullOrEmpty(text) ? token : text; } } [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInPlugin("radamanto.Companions", "Companions", "1.2.4")] [<51d574fa-9559-41c7-ba50-f30c8017450e>Nullable(0)] [<7664ba2c-c0fb-485d-95cb-d6607104ddd1>NullableContext(2)] public class CompanionsPlugin : BaseUnityPlugin { [<7664ba2c-c0fb-485d-95cb-d6607104ddd1>NullableContext(0)] private sealed class ConfigurationManagerAttributes { public bool? Browsable; } internal static ConfigEntry<float> FlightHeight; internal static ConfigEntry<bool> WeightEnabled; [<51d574fa-9559-41c7-ba50-f30c8017450e>Nullable(new byte[] { 2, 1 })] internal static ConfigEntry<string> BlockedItems; internal static ConfigEntry<bool> TeleportCompanion; internal static ConfigEntry<bool> WaitAtDungeonEntrance; internal static ConfigEntry<bool> CatchUpTeleport; internal static ConfigEntry<float> CatchUpDistance; internal static ConfigEntry<bool> ShowMapIcon; internal static ConfigEntry<CompanionCollectionMode> CollectionMode; internal static ConfigEntry<float> CollectionRadius; internal static ConfigEntry<float> CollectionDetectionRadius; internal static ConfigEntry<float> CollectionMaxOwnerDistance; internal static ConfigEntry<CompanionCollectionMode> PickableMode; internal static ConfigEntry<float> PickableDetectionRadius; internal static ConfigEntry<KeyboardShortcut> CallKey; internal static ConfigEntry<KeyboardShortcut> FollowStayKey; internal static ConfigEntry<KeyboardShortcut> OpenChestKey; internal static ConfigEntry<CompanionSelectModifier> SelectModifier; [<51d574fa-9559-41c7-ba50-f30c8017450e>Nullable(1)] public const string PluginId = "radamanto.Companions"; [<51d574fa-9559-41c7-ba50-f30c8017450e>Nullable(1)] public const string PluginName = "Companions"; [<51d574fa-9559-41c7-ba50-f30c8017450e>Nullable(1)] public const string PluginVersion = "1.2.4"; [<51d574fa-9559-41c7-ba50-f30c8017450e>Nullable(1)] internal static readonly Harmony H = new Harmony("radamanto.Companions"); private static bool _bootstrapped; private bool _ownsBootstrap; private bool _quitting; private const float ConfigReloadDelay = 0.5f; internal static ConfigSync ConfigSync; private FileSystemWatcher _configWatcher; private bool _reloadInProgress; private float _reloadAt = -1f; [<7664ba2c-c0fb-485d-95cb-d6607104ddd1>NullableContext(1)] private Dictionary<string, string> LoadEnglishTexts() { try { byte[] array = Localizer.ReadEmbeddedFileBytes("translations.English.yml", typeof(CompanionsPlugin).Assembly); if (array == null) { return new Dictionary<string, string>(); } string input = Encoding.UTF8.GetString(array).TrimStart(new char[1] { '\ufeff' }); return new DeserializerBuilder().Build().Deserialize<Dictionary<string, string>>(input) ?? new Dictionary<string, string>(); } catch (Exception) { return new Dictionary<string, string>(); } } [<7664ba2c-c0fb-485d-95cb-d6607104ddd1>NullableContext(1)] private static string GetEnglishName(Dictionary<string, string> english, string token, string fallback) { string key = (token.StartsWith("$") ? token.Substring(1) : token); if (!english.TryGetValue(key, out var value) || string.IsNullOrWhiteSpace(value)) { return fallback; } string text = Regex.Replace(value, "[=\\n\\t\\\\\"\\'\\[\\]]*", string.Empty).Trim(); return (text.Length > 0) ? text : fallback; } private void BindConfiguration() { //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Expected O, but got Unknown //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Expected O, but got Unknown //IL_0288: Unknown result type (might be due to invalid IL or missing references) //IL_02a9: Unknown result type (might be due to invalid IL or missing references) //IL_02ca: Unknown result type (might be due to invalid IL or missing references) WeightEnabled = Cfg("01 - General", "Enable Weight Limit", defaultValue: true, "If true, overloaded companions stay in place and cannot follow or teleport."); WeightEnabled.SettingChanged += [<7664ba2c-c0fb-485d-95cb-d6607104ddd1>NullableContext(0)] (object _, EventArgs _) => { CompanionWeight.RefreshAll(); }; float value = ((BaseUnityPlugin)this).Config.Bind<float>("02 - Flight", "02.01 - Flight Height", 1f, (ConfigDescription)null).Value; FlightHeight = Cfg("01 - General", "Flight Height", value, "Companion flight height in meters."); string value2 = ((BaseUnityPlugin)this).Config.Bind<string>("03 - Companion Container", "03.01 - Blocked Items", "BlackMetal, BlackMetalScrap, Bronze, BronzeScrap, CharredCogwheel, Copper, CopperOre, CopperScrap, DragonEgg, DvergrNeedle, Flametal, FlametalNew, FlametalOre, FlametalOreNew, Gold, GoldOre, Iron, IronOre, Ironpit, IronScrap, MechanicalSpring, Silver, SilverOre, Tin, TinOre", (ConfigDescription)null).Value; BlockedItems = Cfg("01 - General", "Blocked Items", value2, "Comma-separated prefab names, item tokens, or localized names that companions cannot carry. Vanilla ores are preconfigured."); ((BaseUnityPlugin)this).Config.Remove(new ConfigDefinition("02 - Flight", "02.01 - Flight Height")); ((BaseUnityPlugin)this).Config.Remove(new ConfigDefinition("03 - Companion Container", "03.01 - Blocked Items")); BindContainerConfiguration(); TeleportCompanion = Cfg("02 - Teleport", "02.01 - Follow Through Portals", defaultValue: true, "If true, companions follow their owner through portals and other game teleports. Dungeon entrances are controlled only by 02.02."); WaitAtDungeonEntrance = Cfg("02 - Teleport", "02.02 - Wait At Dungeon Entrance", defaultValue: false, "If true, companions wait at the dungeon entrance while you are inside and rejoin you when you leave. While waiting they do nothing else. If false, they follow you inside. Independent of 02.01."); CatchUpTeleport = Cfg("02 - Teleport", "02.03 - Catch Up Teleport", defaultValue: true, "If true, a following companion that falls too far behind reappears next to its owner with its spawn effect. Companions left behind by a portal while 02.01 is off are not pulled; they resume following once you come back near them."); CatchUpDistance = Cfg("02 - Teleport", "02.04 - Catch Up Distance", 80f, "Distance in meters from the owner that triggers the catch-up teleport, from 20 to 300. Keep it above 05.02 Max Owner Distance so collecting companions are not pulled back.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(20f, 300f)); CollectionMode = Cfg("03 - Collection Dropped", "03.01 - Mode", CompanionCollectionMode.MarkedItems, "Collection of dropped items (items lying on the ground). MarkedItems collects every item type selected in the companion chest into matching stacks and empty chest slots. Select with the key in 05.06 + left-click; doing it on another stack of the same type moves the selection. AllItems collects any allowed ground item. None disables it. Items dropped by other players are never collected."); CollectionDetectionRadius = Cfg("03 - Collection Dropped", "03.02 - Detection Radius", 50f, "Radius in meters for finding dropped items while following, from 1 to 100.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 100f)); PickableMode = Cfg("04 - Collection Pickables", "04.01 - Mode", CompanionCollectionMode.MarkedItems, "Harvesting of pickables such as raspberries, blueberries, mushrooms, thistle, flint and branches. MarkedItems harvests only pickables whose item is selected in the companion chest (same selection used for dropped items). AllItems harvests any pickable whose item is allowed. None disables it. The yield goes straight into the chest; what is blocked or does not fit drops on the ground. Never inside other players' wards."); PickableDetectionRadius = Cfg("04 - Collection Pickables", "04.02 - Detection Radius", 20f, "Radius in meters for finding pickables while following, from 1 to 100. Usually smaller than 03.02, so the companion only harvests what is close to you.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 100f)); CollectionRadius = Cfg("05 - Companion Control", "05.01 - Pickup Radius", 6f, "Distance in meters at which the companion picks up dropped items and harvests pickables, from 1 to 30. A staying companion only collects within this radius.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 30f)); CollectionMaxOwnerDistance = Cfg("05 - Companion Control", "05.02 - Max Owner Distance", 70f, "A following companion stops collecting and returns to you beyond this distance in meters, from 10 to 150.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 150f)); CallKey = Cfg<KeyboardShortcut>("05 - Companion Control", "05.03 - Call Key", CompanionsDefaults.CallKey, "Calls your loaded companions from any distance: whether following, staying or collecting, each one comes next to you and stays there. A companion waiting at a dungeon entrance is left as it is. Set to None to disable. Accepted key names (ranges include every numbered key): None, A-Z, Alpha0-Alpha9, F1-F24, Keypad0-Keypad9, KeypadPeriod, KeypadDivide, KeypadMultiply, KeypadMinus, KeypadPlus, KeypadEnter, KeypadEquals, Backspace, Tab, Clear, Return, Pause, Escape, Space, Delete, Insert, Home, End, PageUp, PageDown, UpArrow, DownArrow, LeftArrow, RightArrow, Numlock, CapsLock, ScrollLock, LeftShift, RightShift, LeftControl, RightControl, LeftAlt, RightAlt, AltGr, LeftCommand, RightCommand, LeftMeta, RightMeta, LeftApple, RightApple, LeftWindows, RightWindows, Help, Print, SysReq, Break, Menu, Exclaim, DoubleQuote, Hash, Dollar, Percent, Ampersand, Quote, LeftParen, RightParen, Asterisk, Plus, Comma, Minus, Period, Slash, Colon, Semicolon, Less, Equals, Greater, Question, At, LeftBracket, Backslash, RightBracket, Caret, Underscore, BackQuote, LeftCurlyBracket, Pipe, RightCurlyBracket, Tilde, Mouse0-Mouse6, WheelUp, WheelDown, JoystickButton0-JoystickButton19 and Joystick1Button0-Joystick8Button19 (joysticks 1-8, buttons 0-19). Use one key name or combine names with +, e.g. H, Mouse3, E + LeftShift, H + LeftControl + LeftAlt. Mouse0 = left, Mouse1 = right, Mouse2 = middle, Mouse3-Mouse6 = additional buttons. Gamepad mode keeps the game's bindings.", null, synced: false); FollowStayKey = Cfg<KeyboardShortcut>("05 - Companion Control", "05.04 - Follow Stay Key", CompanionsDefaults.FollowStayKey, "Key pressed while looking at your companion up close to toggle follow / stay. Set to None to disable. Gamepads keep the game's interact button. Accepted key names (ranges include every numbered key): None, A-Z, Alpha0-Alpha9, F1-F24, Keypad0-Keypad9, KeypadPeriod, KeypadDivide, KeypadMultiply, KeypadMinus, KeypadPlus, KeypadEnter, KeypadEquals, Backspace, Tab, Clear, Return, Pause, Escape, Space, Delete, Insert, Home, End, PageUp, PageDown, UpArrow, DownArrow, LeftArrow, RightArrow, Numlock, CapsLock, ScrollLock, LeftShift, RightShift, LeftControl, RightControl, LeftAlt, RightAlt, AltGr, LeftCommand, RightCommand, LeftMeta, RightMeta, LeftApple, RightApple, LeftWindows, RightWindows, Help, Print, SysReq, Break, Menu, Exclaim, DoubleQuote, Hash, Dollar, Percent, Ampersand, Quote, LeftParen, RightParen, Asterisk, Plus, Comma, Minus, Period, Slash, Colon, Semicolon, Less, Equals, Greater, Question, At, LeftBracket, Backslash, RightBracket, Caret, Underscore, BackQuote, LeftCurlyBracket, Pipe, RightCurlyBracket, Tilde, Mouse0-Mouse6, WheelUp, WheelDown, JoystickButton0-JoystickButton19 and Joystick1Button0-Joystick8Button19 (joysticks 1-8, buttons 0-19). Use one key name or combine names with +, e.g. H, Mouse3, E + LeftShift, H + LeftControl + LeftAlt. Mouse0 = left, Mouse1 = right, Mouse2 = middle, Mouse3-Mouse6 = additional buttons. Gamepad mode keeps the game's bindings.", null, synced: false); OpenChestKey = Cfg<KeyboardShortcut>("05 - Companion Control", "05.05 - Open Chest Key", CompanionsDefaults.OpenChestKey, "Key pressed while looking at your companion up close to open its chest. Set to None to disable. Gamepads keep the game's alternate interact. Accepted key names (ranges include every numbered key): None, A-Z, Alpha0-Alpha9, F1-F24, Keypad0-Keypad9, KeypadPeriod, KeypadDivide, KeypadMultiply, KeypadMinus, KeypadPlus, KeypadEnter, KeypadEquals, Backspace, Tab, Clear, Return, Pause, Escape, Space, Delete, Insert, Home, End, PageUp, PageDown, UpArrow, DownArrow, LeftArrow, RightArrow, Numlock, CapsLock, ScrollLock, LeftShift, RightShift, LeftControl, RightControl, LeftAlt, RightAlt, AltGr, LeftCommand, RightCommand, LeftMeta, RightMeta, LeftApple, RightApple, LeftWindows, RightWindows, Help, Print, SysReq, Break, Menu, Exclaim, DoubleQuote, Hash, Dollar, Percent, Ampersand, Quote, LeftParen, RightParen, Asterisk, Plus, Comma, Minus, Period, Slash, Colon, Semicolon, Less, Equals, Greater, Question, At, LeftBracket, Backslash, RightBracket, Caret, Underscore, BackQuote, LeftCurlyBracket, Pipe, RightCurlyBracket, Tilde, Mouse0-Mouse6, WheelUp, WheelDown, JoystickButton0-JoystickButton19 and Joystick1Button0-Joystick8Button19 (joysticks 1-8, buttons 0-19). Use one key name or combine names with +, e.g. H, Mouse3, E + LeftShift, H + LeftControl + LeftAlt. Mouse0 = left, Mouse1 = right, Mouse2 = middle, Mouse3-Mouse6 = additional buttons. Gamepad mode keeps the game's bindings.", null, synced: false); SelectModifier = Cfg("05 - Companion Control", "05.06 - Select For Collection Key", CompanionSelectModifier.Alt, "Hold this key and left-click an item in the companion chest to select or clear it for collection (dropped items and pickables). Accepted values: Alt (LeftAlt or RightAlt), Ctrl (LeftControl or RightControl), Shift (LeftShift or RightShift).", null, synced: false); ShowMapIcon = Cfg("06 - Map", "06.01 - Show Map Icon", defaultValue: true, "If true, your companions are shown on the minimap and the large map, at any distance."); FlightHeight.SettingChanged += [<7664ba2c-c0fb-485d-95cb-d6607104ddd1>NullableContext(0)] (object _, EventArgs _) => { CompanionsFlight.RefreshHeight(); }; CallKey.SettingChanged += [<7664ba2c-c0fb-485d-95cb-d6607104ddd1>NullableContext(0)] (object _, EventArgs _) => { CompanionsControls.InvalidateLabels(); }; FollowStayKey.SettingChanged += [<7664ba2c-c0fb-485d-95cb-d6607104ddd1>NullableContext(0)] (object _, EventArgs _) => { CompanionsControls.InvalidateLabels(); }; OpenChestKey.SettingChanged += [<7664ba2c-c0fb-485d-95cb-d6607104ddd1>NullableContext(0)] (object _, EventArgs _) => { CompanionsControls.InvalidateLabels(); }; BlockedItems.SettingChanged += [<7664ba2c-c0fb-485d-95cb-d6607104ddd1>NullableContext(0)] (object _, EventArgs _) => { CompanionsContainer.ReloadBlocklist(BlockedItems.Value); }; CollectionMode.SettingChanged += [<7664ba2c-c0fb-485d-95cb-d6607104ddd1>NullableContext(0)] (object _, EventArgs _) => { CompanionCollector.RefreshSensors(); }; CollectionRadius.SettingChanged += [<7664ba2c-c0fb-485d-95cb-d6607104ddd1>NullableContext(0)] (object _, EventArgs _) => { CompanionCollector.RefreshSensors(); }; CollectionDetectionRadius.SettingChanged += [<7664ba2c-c0fb-485d-95cb-d6607104ddd1>NullableContext(0)] (object _, EventArgs _) => { CompanionCollector.RefreshSensors(); }; CollectionMaxOwnerDistance.SettingChanged += [<7664ba2c-c0fb-485d-95cb-d6607104ddd1>NullableContext(0)] (object _, EventArgs _) => { CompanionCollector.RefreshSensors(); }; PickableMode.SettingChanged += [<7664ba2c-c0fb-485d-95cb-d6607104ddd1>NullableContext(0)] (object _, EventArgs _) => { CompanionCollector.RefreshSensors(); }; PickableDetectionRadius.SettingChanged += [<7664ba2c-c0fb-485d-95cb-d6607104ddd1>NullableContext(0)] (object _, EventArgs _) => { CompanionCollector.RefreshSensors(); }; CompanionsContainer.ReloadBlocklist(BlockedItems.Value); } private void BindContainerConfiguration() { Dictionary<string, string> english = LoadEnglishTexts(); CompanionDefinition[] all = CompanionsRegistry.All; foreach (CompanionDefinition definition in all) { string englishName = GetEnglishName(english, definition.CompanionNameToken, "Companion " + definition.Id); string section = "07." + definition.Id + " - " + englishName + " Container"; ConfigEntry<int> width = Cfg(section, "01 - Width", definition.DefaultContainerWidth, "Container width for the " + englishName + ", from 1 to 8.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 8)); ConfigEntry<int> height = Cfg(section, "02 - Height", definition.DefaultContainerHeight, "Container height for the " + englishName + ", from 1 to 8.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 8)); float defaultValue = (definition.CompanionPrefab.EndsWith("_baby") ? 300f : (definition.CompanionPrefab.EndsWith("_big") ? 1000f : 500f)); ConfigEntry<float> maxWeight = Cfg(section, "03 - Maximum Weight", defaultValue, "Maximum carry weight for the " + englishName + " before it stops moving.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 1000000f)); definition.MaxCarryWeight = maxWeight.Value; maxWeight.SettingChanged += [<7664ba2c-c0fb-485d-95cb-d6607104ddd1>NullableContext(0)] (object _, EventArgs _) => { definition.MaxCarryWeight = maxWeight.Value; CompanionWeight.RefreshAll(); }; definition.ContainerWidth = width.Value; definition.ContainerHeight = height.Value; width.SettingChanged += [<7664ba2c-c0fb-485d-95cb-d6607104ddd1>NullableContext(0)] (object _, EventArgs _) => { definition.ContainerWidth = width.Value; }; height.SettingChanged += [<7664ba2c-c0fb-485d-95cb-d6607104ddd1>NullableContext(0)] (object _, EventArgs _) => { definition.ContainerHeight = height.Value; }; } } private void Awake() { if (!_bootstrapped && CompanionsAssets.LoadBundle(out var _)) { Localizer.Load(); _ownsBootstrap = true; bool saveOnConfigSet = ((BaseUnityPlugin)this).Config.SaveOnConfigSet; ((BaseUnityPlugin)this).Config.SaveOnConfigSet = false; try { SetupServerSync(); BindConfiguration(); CompanionsAssets.Register(); CompanionsAudio.Initialize(CompanionsAssets.Bundle); H.PatchAll(); CompanionsInvoker.Initialize(); _bootstrapped = true; } finally { ((BaseUnityPlugin)this).Config.SaveOnConfigSet = saveOnConfigSet; } ((BaseUnityPlugin)this).Config.Save(); SetupConfigWatcher(); } } private void OnApplicationQuit() { _quitting = true; } private void OnDestroy() { if (_ownsBootstrap) { if (!_quitting) { CompanionsInvoker.Unregister(); } CompanionsNetwork.Unregister(); H.UnpatchSelf(); DisposeConfigWatcher(); ClearStaticState(); _bootstrapped = false; } } private static void ClearStaticState() { CompanionsInvoker.Reset(); CompanionsNetwork.Reset(); CompanionsTracker.Reset(); CompanionsCatchUp.Reset(); CompanionsTeleport.Reset(); CompanionsCollectionSelection.Close(); CompanionsMapIcons.Clear(); CompanionsControls.InvalidateLabels(); CompanionCollector.ResetStatics(); } private void Update() { if (!(_reloadAt < 0f) && !(Time.realtimeSinceStartup < _reloadAt)) { _reloadAt = -1f; ReloadConfig(); } } private void SetupServerSync() { //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Expected O, but got Unknown ConfigSync = new ConfigSync(((BaseUnityPlugin)this).Info.Metadata.GUID) { DisplayName = ((BaseUnityPlugin)this).Info.Metadata.Name, CurrentVersion = ((BaseUnityPlugin)this).Info.Metadata.Version.ToString(), MinimumRequiredVersion = ((BaseUnityPlugin)this).Info.Metadata.Version.ToString(), ModRequired = true }; ConfigEntry<bool> lockingConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("01 - General", "Lock Configuration", true, new ConfigDescription("If true, the server locks synchronized configuration values.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Browsable = false } })); ConfigSync.AddLockingConfigEntry<bool>(lockingConfig); } [<7664ba2c-c0fb-485d-95cb-d6607104ddd1>NullableContext(1)] private ConfigEntry<T> Cfg<[<51d574fa-9559-41c7-ba50-f30c8017450e>Nullable(2)] T>(string section, string key, T defaultValue, string description, [<51d574fa-9559-41c7-ba50-f30c8017450e>Nullable(2)] AcceptableValueBase acceptableValues = null, bool synced = true) { //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Expected O, but got Unknown //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Expected O, but got Unknown if (ConfigSync == null) { throw new InvalidOperationException("ServerSync has not been initialized."); } if (1 == 0) { } string text = section switch { "02 - Teleport" => "04 - Teleport", "03 - Collection Dropped" => "05 - Collection Dropped", "04 - Collection Pickables" => "06 - Collection Pickables", "05 - Companion Control" => "07 - Companion Control", "06 - Map" => "08 - Map", _ => (!section.StartsWith("07.")) ? null : ("03" + section.Substring(2)), }; if (1 == 0) { } string text2 = text; if (text2 != null) { string text3 = (key.StartsWith(section.Substring(0, 2) + ".") ? (text2.Substring(0, 2) + key.Substring(2)) : key); defaultValue = ((BaseUnityPlugin)this).Config.Bind<T>(text2, text3, defaultValue, (ConfigDescription)null).Value; ((BaseUnityPlugin)this).Config.Remove(new ConfigDefinition(text2, text3)); } ConfigDescription val = new ConfigDescription(description + (synced ? " [Synced with Server]" : " [Not Synced with Server]"), acceptableValues, Array.Empty<object>()); ConfigEntry<T> val2 = ((BaseUnityPlugin)this).Config.Bind<T>(section, key, defaultValue, val); ConfigSync.AddConfigEntry<T>(val2).SynchronizedConfig = synced; return val2; } private void SetupConfigWatcher() { try { _configWatcher?.Dispose(); _configWatcher = new FileSystemWatcher(Path.GetDirectoryName(((BaseUnityPlugin)this).Config.ConfigFilePath), Path.GetFileName(((BaseUnityPlugin)this).Config.ConfigFilePath)) { IncludeSubdirectories = false, NotifyFilter = (NotifyFilters.FileName | NotifyFilters.Size | NotifyFilters.LastWrite), SynchronizingObject = ThreadingHelper.SynchronizingObject }; FileSystemEventHandler value = [<7664ba2c-c0fb-485d-95cb-d6607104ddd1>NullableContext(0)] (object _, FileSystemEventArgs _) => { ScheduleConfigReload(); }; _configWatcher.Changed += value; _configWatcher.Created += value; _configWatcher.Renamed += [<7664ba2c-c0fb-485d-95cb-d6607104ddd1>NullableContext(0)] (object _, RenamedEventArgs _) => { ScheduleConfigReload(); }; _configWatcher.EnableRaisingEvents = true; } catch (Exception) { _configWatcher?.Dispose(); _configWatcher = null; } } private void ScheduleConfigReload() { if (!((Behaviour)this).isActiveAndEnabled) { ReloadConfig(); } else { _reloadAt = Time.realtimeSinceStartup + 0.5f; } } private void ReloadConfig() { if (_reloadInProgress) { return; } bool saveOnConfigSet = ((BaseUnityPlugin)this).Config.SaveOnConfigSet; try { _reloadInProgress = true; if (_configWatcher != null) { _configWatcher.EnableRaisingEvents = false; } ((BaseUnityPlugin)this).Config.SaveOnConfigSet = false; ((BaseUnityPlugin)this).Config.Reload(); } catch (Exception) { } finally { ((BaseUnityPlugin)this).Config.SaveOnConfigSet = saveOnConfigSet; _reloadInProgress = false; if (_configWatcher != null) { _configWatcher.EnableRaisingEvents = true; } } } private void DisposeConfigWatcher() { _reloadAt = -1f; if (_configWatcher != null) { _configWatcher.EnableRaisingEvents = false; _configWatcher.Dispose(); _configWatcher = null; } } } [<51d574fa-9559-41c7-ba50-f30c8017450e>Nullable(0)] [<7664ba2c-c0fb-485d-95cb-d6607104ddd1>NullableContext(1)] internal static class CompanionsInvoker { [<7664ba2c-c0fb-485d-95cb-d6607104ddd1>NullableContext(0)] [HarmonyPatch(typeof(ItemData), "IsEquipable")] private static class ItemData_IsEquipable_CompanionInvoker_Patch { [<7664ba2c-c0fb-485d-95cb-d6607104ddd1>NullableContext(1)] private static void Postfix(ItemData __instance, ref bool __result) { if (IsInvoker(__instance)) { __result = true; } } } [<7664ba2c-c0fb-485d-95cb-d6607104ddd1>NullableContext(0)] [HarmonyPatch(typeof(Humanoid), "EquipItem", new Type[] { typeof(ItemData), typeof(bool) })] private static class Humanoid_EquipItem_CompanionInvoker_Patch { [<7664ba2c-c0fb-485d-95cb-d6607104ddd1>NullableContext(1)] private static bool Prefix(Humanoid __instance, ItemData item, bool triggerEquipEffects, ref bool __result) { //IL_007a: Unknown result type (might be due to invalid IL or missing references) if (!(__instance is Player) || !IsInvoker(item)) { return true; } ItemData equipped = GetEquipped(__instance); if (equipped == item) { __result = !triggerEquipEffects && item.m_equipped; return false; } if (!CanEquip(__instance, item)) { __result = false; return false; } if (equipped != null) { if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer) { ((Character)(Player)__instance).Message((MessageType)2, CompanionsLocalization.Localize("$companions_msg_unequip_first"), 0, (Sprite)null, false); } __result = false; return false; } item.m_equipped = true; SetEquipped(__instance, item); RefreshEquipment(__instance); __result = true; if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer) { _pendingSummon = true; ProcessPendingSummon(); } return false; } } [<51d574fa-9559-41c7-ba50-f30c8017450e>Nullable(0)] [HarmonyPatch(typeof(Humanoid), "UnequipItem", new Type[] { typeof(ItemData), typeof(bool) })] private static class Humanoid_UnequipItem_CompanionInvoker_Patch { private static bool Prefix(Humanoid __instance, ItemData item, bool triggerEquipEffects, out bool __state) { //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Expected O, but got Unknown __state = false; if (!(__instance is Player) || item == null || !item.m_equipped || !IsInvoker(item)) { return true; } if (_playerDeathInProgress || _internalMove) { return false; } if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer && !ApprovedUnequip.Contains(item)) { BeginUnequip((Player)__instance, item, triggerEquipEffects); return false; } __state = true; return true; } private static void Postfix(Humanoid __instance, ItemData item, bool __state) { //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Expected O, but got Unknown //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Expected O, but got Unknown if (!__state || item.m_equipped) { return; } SetEquipped(__instance, null); RefreshEquipment(__instance); if (!((Object)(object)__instance == (Object)(object)Player.m_localPlayer)) { return; } CompanionDefinition companionDefinition = CompanionsRegistry.ForInvoker(item); if (companionDefinition != null) { if (_offlineUnequip) { UnsummonOffline((Player)__instance, companionDefinition, discardItems: false); } else { RequestUnsummon((Player)__instance, companionDefinition, _discardOnCompletedUnequip, fromUnequip: true); } } } } [<7664ba2c-c0fb-485d-95cb-d6607104ddd1>NullableContext(0)] [HarmonyPatch(typeof(Player), "OnDeath")] private static class Player_OnDeath_CompanionInvoker_Patch { [<7664ba2c-c0fb-485d-95cb-d6607104ddd1>NullableContext(1)] private static void Prefix(Player __instance) { _playerDeathInProgress = true; if (!((Object)(object)__instance == (Object)null) && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && ((Character)__instance).IsOwner()) { CompanionsDeathDrop.DropLoaded(__instance); CompanionsNetwork.SendRequest(CompanionsNetwork.NextRequestId(), CompanionOp.DeathDrop, null, option: false, 30f); } } [<7664ba2c-c0fb-485d-95cb-d6607104ddd1>NullableContext(2)] private static Exception Finalizer(Exception __exception) { _playerDeathInProgress = false; return __exception; } } [HarmonyPatch(typeof(Humanoid), "IsItemEquiped", new Type[] { typeof(ItemData) })] [<7664ba2c-c0fb-485d-95cb-d6607104ddd1>NullableContext(0)] private static class Humanoid_IsItemEquiped_CompanionInvoker_Patch { [<7664ba2c-c0fb-485d-95cb-d6607104ddd1>NullableContext(1)] private static void Postfix(Humanoid __instance, ItemData item, ref bool __result) { if (__instance is Player && IsInvoker(item) && GetEquipped(__instance) == item) { __result = true; } } } [<7664ba2c-c0fb-485d-95cb-d6607104ddd1>NullableContext(0)] [HarmonyPatch(typeof(Humanoid), "UnequipAllItems")] private static class Humanoid_UnequipAllItems_CompanionInvoker_Patch { [<7664ba2c-c0fb-485d-95cb-d6607104ddd1>NullableContext(1)] private static void Prefix(Humanoid __instance) { if (__instance is Player) { ItemData equipped = GetEquipped(__instance); if (equipped != null) { __instance.UnequipItem(equipped, false); } } } } [<7664ba2c-c0fb-485d-95cb-d6607104ddd1>NullableContext(0)] [HarmonyPatch(typeof(Humanoid), "DropItem", new Type[] { typeof(Inventory), typeof(ItemData), typeof(int) })] private static class Humanoid_DropItem_CompanionInvoker_Patch { [<7664ba2c-c0fb-485d-95cb-d6607104ddd1>NullableContext(1)] private static bool Prefix(Humanoid __instance, ItemData item, ref bool __result) { if (!(__instance is Player) || !IsInvoker(item) || !item.m_equipped) { return true; } if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer) { CompanionsContainer.Show("$companions_msg_unequip_first"); } __result = false; return false; } } [HarmonyPatch(typeof(InventoryGui), "OnSelectedItem", new Type[] { typeof(InventoryGrid), typeof(ItemData), typeof(Vector2i), typeof(Modifier) })] [<7664ba2c-c0fb-485d-95cb-d6607104ddd1>NullableContext(0)] private static class InventoryGui_OnSelectedItem_CompanionInvoker_Patch { [<7664ba2c-c0fb-485d-95cb-d6607104ddd1>NullableContext(1)] private static bool Prefix(InventoryGui __instance, InventoryGrid grid, ItemData item, Vector2i pos, Modifier mod) { //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Invalid comparison between Unknown and I4 if ((Object)(object)grid == (Object)null) { return true; } Inventory inventory = grid.GetInventory(); Container currentContainer = __instance.m_currentContainer; bool flag = (Object)(object)__instance.m_dragGo != (Object)null; bool num; if (!flag) { if ((int)mod != 2 || !((Object)(object)currentContainer != (Object)null)) { goto IL_0086; } num = BlocksTransfer(inventory, item, currentContainer.GetInventory()); } else { num = BlocksDrop(inventory, __instance.m_dragInventory, __instance.m_dragItem, __instance.m_dragAmount, pos); } if (num) { CompanionsContainer.Show("$companions_msg_unequip_first"); return false; } goto IL_0086; IL_0086: _internalMove = flag && IsLocalInventory(inventory) && inventory == __instance.m_dragInventory; return true; } [<7664ba2c-c0fb-485d-95cb-d6607104ddd1>NullableContext(2)] private static Exception Finalizer(Exception __exception) { _internalMove = false; return __exception; } } [HarmonyPatch(typeof(InventoryGui), "DoCrafting", new Type[] { typeof(Player) })] [<7664ba2c-c0fb-485d-95cb-d6607104ddd1>NullableContext(0)] private static class InventoryGui_DoCrafting_CompanionInvoker_Patch { [<7664ba2c-c0fb-485d-95cb-d6607104ddd1>NullableContext(1)] private static bool Prefix(InventoryGui __instance, Player player) { if ((Object)(object)player == (Object)null || (Object)(object)player != (Object)(object)Player.m_localPlayer || (Object)(object)__instance.m_craftRecipe == (Object)null) { return true; } ItemData equipped = GetEquipped((Humanoid)(object)player); if (equipped == null) { return true; } Requirement[] resources = __instance.m_craftRecipe.m_resources; foreach (Requirement val in resources) { if (!((Object)(object)val.m_resItem == (Object)null) && !(val.m_resItem.m_itemData.m_shared.m_name != equipped.m_shared.m_name)) { CompanionsContainer.Show("$companions_msg_unequip_first"); return false; } } return true; } } [HarmonyPatch(typeof(Inventory), "MoveItemToThis", new Type[] { typeof(Inventory), typeof(ItemData) })] [<7664ba2c-c0fb-485d-95cb-d6607104ddd1>NullableContext(0)] private static class Inventory_MoveItemToThis_CompanionInvoker_Patch { [<7664ba2c-c0fb-485d-95cb-d6607104ddd1>NullableContext(1)] private static bool Prefix(Inventory __instance, Inventory fromInventory, ItemData item) { if (!BlocksTransfer(fromInventory, item, __instance)) { return true; } CompanionsContainer.Show("$companions_msg_unequip_first"); return false; } } [<7664ba2c-c0fb-485d-95cb-d6607104ddd1>NullableContext(0)] [HarmonyPatch(typeof(Player), "OnSpawned", new Type[] { typeof(bool) })] private static class Player_OnSpawned_CompanionInvoker_Patch { [<7664ba2c-c0fb-485d-95cb-d6607104ddd1>NullableContext(1)] private static void Postfix(Player __instance) { if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer)) { Initialize(); Resync((Humanoid)(object)__instance); if (GetEquipped((Humanoid)(object)__instance) != null) { RefreshEquipment((Humanoid)(object)__instance); _pendingSummon = !CompanionsNetwork.IsPending(_summonRequestId); } else { _reconcilePending = true; } ProcessPendingSummon(); } } } [<7664ba2c-c0fb-485d-95cb-d6607104ddd1>NullableContext(0)] [HarmonyPatch(typeof(Humanoid), "OnDestroy")] private static class Humanoid_OnDestroy_CompanionInvoker_Patch { [<7664ba2c-c0fb-485d-95cb-d6607104ddd1>NullableContext(1)] private static void Postfix(Humanoid __instance) { if (__instance is Player) { EquippedItems.Remove(__instance); EmptyResyncAt.Remove(__instance); if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer) { ClearPendingUnequip(); ClearUnequipUnsummon(); _pendingSummon = false; _summonRequestId = 0; ResetReconcile(); } } } } private const float EmptyResyncInterval = 1f; private const float UnequipReplyBudget = 10f; private const float RequestBudget = 30f; private const float SummonGraceSeconds = 10f; [<51d574fa-9559-41c7-ba50-f30c8017450e>Nullable(new byte[] { 1, 1, 2 })] private static readonly Dictionary<Humanoid, ItemData> EquippedItems = new Dictionary<Humanoid, ItemData>(); private static readonly Dictionary<Humanoid, float> EmptyResyncAt = new Dictionary<Humanoid, float>(); private static readonly HashSet<ItemData> ApprovedUnequip = new HashSet<ItemData>(); private static readonly List<CompanionDefinition> ReconcileQueue = new List<CompanionDefinition>(); private static readonly List<bool> ReconcileHasItems = new List<bool>(); private static bool _slotRegistered; private static bool _pendingSummon; private static bool _playerDeathInProgress; private static bool _reconcilePending; private static bool _reconcileRunning; private static bool _offlineUnequip; private static bool _internalMove; [<51d574fa-9559-41c7-ba50-f30c8017450e>Nullable(2)] private static ItemData _pendingUnequipItem; private static bool _pendingUnequipEffects; private static bool _pendingUnequipAwaitingServer; private static bool _discardOnCompletedUnequip; private static int _pendingUnequipRequestId; private static int _summonRequestId; private static int _reconcileRequestId; private static int _unequipUnsummonRequestId; [<51d574fa-9559-41c7-ba50-f30c8017450e>Nullable(2)] private static CompanionDefinition _unequipUnsummonDefinition; internal static void Initialize() { if (!_slotRegistered && AzuEpiApi.IsLoaded()) { _slotRegistered = AzuEpiApi.AddSlot("$companions_slot_name", (Player player) => GetEquipped((Humanoid)(object)player), IsInvoker, -1); } } internal static void Unregister() { if (_slotRegistered && AzuEpiApi.RemoveSlot("$companions_slot_name")) { _slotRegistered = false; } } internal static void Reset() { EquippedItems.Clear(); EmptyResyncAt.Clear(); ApprovedUnequip.Clear(); ClearPendingUnequip(); ClearUnequipUnsummon(); ResetReconcile(); _pendingSummon = false; _playerDeathInProgress = false; _reconcileRunning = false; _offlineUnequip = false; _internalMove = false; _discardOnCompletedUnequip = false; _summonRequestId = 0; } [<7664ba2c-c0fb-485d-95cb-d6607104ddd1>NullableContext(2)] private static bool IsInvoker(ItemData item) { return CompanionsRegistry.ForInvoker(item) != null; } [return: <51d574fa-9559-41c7-ba50-f30c8017450e>Nullable(2)] internal static CompanionDefinition GetEquippedDefinition(Player player) { return CompanionsRegistry.ForInvoker(GetEquipped((Humanoid)(object)player)); } [<7664ba2c-c0fb-485d-95cb-d6607104ddd1>NullableContext(2)] internal static bool BlocksTransfer(Inventory from, ItemData item, Inventory to) { return to != null && item != null && from != to && IsLocalInventory(from) && item.m_equipped && IsInvoker(item); } [<7664ba2c-c0fb-485d-95cb-d6607104ddd1>NullableContext(2)] internal static bool BlocksDrop(Inventory target, Inventory from, ItemData item, int amount, Vector2i position) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) if (target == null || from == null || item == null) { return false; } if (BlocksTransfer(from, item, target)) { return true; } ItemData itemAt = target.GetItemAt(position.x, position.y); return CompanionsContainer.WouldSwap(itemAt, item, amount) && BlocksTransfer(target, itemAt, from); } [<7664ba2c-c0fb-485d-95cb-d6607104ddd1>NullableContext(2)] private static bool IsLocalInventory(Inventory inventory) { Player localPlayer = Player.m_localPlayer; return (Object)(object)localPlayer != (Object)null && inventory != null && inventory == ((Humanoid)localPlayer).GetInventory(); } private static void ResetReconcile() { _reconcilePending = false; _reconcileRequestId = 0; ReconcileQueue.Clear(); ReconcileHasItems.Clear(); } private static bool ShowDiscardPopup(Player player, Action yes, Action no) { //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Expected O, but got Unknown //IL_006e: Expected O, but got Unknown //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Expected O, but got Unknown if (!UnifiedPopup.IsAvailable()) { ((Character)player).Message((MessageType)2, CompanionsLocalization.Localize("$companions_msg_popup_unavailable"), 0, (Sprite)null, false); return false; } UnifiedPopup.Push((PopupBase)new YesNoPopup(CompanionsLocalization.Localize("$companions_popup_title"), CompanionsLocalization.Localize("$companions_popup_discard"), (PopupButtonCallback)delegate { UnifiedPopup.Pop(); yes(); }, (PopupButtonCallback)delegate { UnifiedPopup.Pop(); no(); }, false, false)); return true; } internal static void ProcessPendingSummon() { Initialize(); Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return; } ItemData equipped = GetEquipped((Humanoid)(object)localPlayer); if (equipped == null) { _pendingSummon = false; if (_reconcilePending) { StartReconcile(localPlayer); } } else { if (!_pendingSummon || CompanionsNetwork.IsPending(_summonRequestId)) { return; } CompanionDefinition companionDefinition = CompanionsRegistry.ForInvoker(equipped); if (companionDefinition == null) { _pendingSummon = false; return; } int requestId = (_summonRequestId = CompanionsNetwork.NextRequestId()); _pendingSummon = false; if (CompanionsNetwork.SendRequest(requestId, CompanionOp.Summon, companionDefinition, option: false, 30f)) { CompanionsCatchUp.SuppressCatchUp(localPlayer, 10f); return; } _summonRequestId = 0; _pendingSummon = true; } } internal static void RequestFollowerSummon(Player player, CompanionDefinition definition) { if (!((Object)(object)player == (Object)null) && definition != null && GetEquippedDefinition(player) == definition && !CompanionsNetwork.IsPending(_summonRequestId) && !CompanionsNetwork.SendRequest(_summonRequestId = CompanionsNetwork.NextRequestId(), CompanionOp.Summon, definition, option: true, 30f)) { _summonRequestId = 0; } } private static void StartReconcile(Player player) { if (!_reconcileRunning && !CompanionsNetwork.IsPending(_reconcileRequestId)) { ReconcileQueue.Clear(); ReconcileHasItems.Clear(); int requestId = (_reconcileRequestId = CompanionsNetwork.NextRequestId()); _reconcilePending = false; if (!CompanionsNetwork.SendRequest(requestId, CompanionOp.Check, null, option: false, 30f)) { _reconcileRequestId = 0; _reconcilePending = true; } } } internal static void OnResponse(CompanionRequest request, CompanionStatus status, ZPackage data) { switch (request.Op) { case CompanionOp.Summon: OnSummonResponse(request, status, data); break; case CompanionOp.Check: if (request.Id == _pendingUnequipRequestId) { OnUnequipCheck(status); } else if (request.Id == _reconcileRequestId) { OnReconcileCheck(status, data); } break; case CompanionOp.Unsummon: OnUnsummonResponse(request, status); break; } Player localPlayer = Player.m_localPlayer; if (_reconcilePending && (Object)(object)localPlayer != (Object)null) { StartReconcile(localPlayer); } } internal static void OnTimeout(CompanionRequest request) { Player localPlayer = Player.m_localPlayer; switch (request.Op) { case CompanionOp.Summon: if (request.Id == _summonRequestId) {