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 LightMyFire v1.1.0
plugins/LightMyFire/LightMyFire.dll
Decompiled a day ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Reflection; using System.Runtime.CompilerServices; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using Jotunn.Utils; using TMPro; using UnityEngine; using UnityEngine.Rendering; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("LightMyFire")] [assembly: AssemblyFileVersion("1.1.0")] [assembly: AssemblyCompany("R4V9N1")] [assembly: AssemblyDescription("Created by R4V9N1")] [assembly: AssemblyProduct("LightMyFire")] [assembly: AssemblyCopyright("Created by R4V9N1")] [assembly: AssemblyMetadata("Creator", "Created by R4V9N1")] [assembly: AssemblyVersion("1.1.0.0")] namespace LightMyFire; public sealed class LightMyFireBarrel : MonoBehaviour { private struct PendingReservation { public int Amount; public long RequesterPeer; public ZDOID FireplaceId; public long ReservedAtNetworkTicks; } private const string RpcRequestFuel = "R4V9N1_LightMyFire_RequestFuel"; private const string RpcAckApplied = "R4V9N1_LightMyFire_AckApplied"; private const string RpcRefundFuel = "R4V9N1_LightMyFire_RefundFuel"; internal const int MaxRequestPerTransaction = 50; private const float ReservationTimeoutSeconds = 30f; private const string ReservationStateZdoKey = "R4V9N1_LightMyFire_PendingReservations"; private static readonly List<LightMyFireBarrel> ActiveBarrels = new List<LightMyFireBarrel>(); private ZNetView _nview; private Container _container; private Inventory _inventory; [SerializeField] private string _fuelItemName; private bool _rpcRegistered; private bool _inventoryHooksRegistered; private bool _runtimeInitialized; private bool _sanitizingInventory; private bool _ownershipStateInitialized; private bool _wasOwner; private readonly Dictionary<long, PendingReservation> _pendingReservations = new Dictionary<long, PendingReservation>(); private float _nextReservationSweep; internal string FuelItemName { get { EnsureConfiguration(); return _fuelItemName; } } internal void Configure(string fuelItemName) { _fuelItemName = fuelItemName; } private void Awake() { _nview = ((Component)this).GetComponent<ZNetView>(); _container = ((Component)this).GetComponent<Container>(); EnsureConfiguration(); } private void Start() { TryInitializeRuntime(); } private void Update() { if (!_runtimeInitialized) { TryInitializeRuntime(); } else { RefreshOwnershipState(); } } private bool TryInitializeRuntime() { EnsureConfiguration(); if ((Object)(object)_nview == (Object)null) { _nview = ((Component)this).GetComponent<ZNetView>(); } if ((Object)(object)_container == (Object)null) { _container = ((Component)this).GetComponent<Container>(); } if ((Object)(object)_container == (Object)null) { return false; } if (_inventory == null) { _inventory = _container.GetInventory(); } if (_inventory != null && !_inventoryHooksRegistered) { Inventory inventory = _inventory; inventory.m_onChanged = (Action)Delegate.Combine(inventory.m_onChanged, new Action(OnInventoryChanged)); LightMyFireItemFilter.RegisterFilteredInventory(_inventory, _fuelItemName); _inventoryHooksRegistered = true; } if ((Object)(object)_nview == (Object)null || !_nview.IsValid() || _nview.GetZDO() == null || _inventory == null) { return false; } if (!_rpcRegistered) { _nview.Register<long, ZDOID, int>("R4V9N1_LightMyFire_RequestFuel", (Action<long, long, ZDOID, int>)RPC_RequestFuel); _nview.Register<long>("R4V9N1_LightMyFire_AckApplied", (Action<long, long>)RPC_AckApplied); _nview.Register<long, int>("R4V9N1_LightMyFire_RefundFuel", (Action<long, long, int>)RPC_RefundFuel); _rpcRegistered = true; } if (!ActiveBarrels.Contains(this)) { ActiveBarrels.Add(this); } RefreshOwnershipState(); _runtimeInitialized = true; LightMyFirePlugin.LogBarrelRuntimeReady(((Object)((Component)this).gameObject).name, _fuelItemName, GetFuelCount()); return true; } private void EnsureConfiguration() { if (string.IsNullOrEmpty(_fuelItemName)) { if (((Object)((Component)this).gameObject).name.IndexOf("ResinBarrel", StringComparison.OrdinalIgnoreCase) >= 0) { _fuelItemName = "$item_resin"; } else if (((Object)((Component)this).gameObject).name.IndexOf("WoodBarrel", StringComparison.OrdinalIgnoreCase) >= 0) { _fuelItemName = "$item_wood"; } else { _fuelItemName = "$item_coal"; } } } private void OnDestroy() { if (_inventory != null && _inventoryHooksRegistered) { Inventory inventory = _inventory; inventory.m_onChanged = (Action)Delegate.Remove(inventory.m_onChanged, new Action(OnInventoryChanged)); LightMyFireItemFilter.UnregisterFilteredInventory(_inventory); _inventoryHooksRegistered = false; } _inventory = null; _runtimeInitialized = false; _rpcRegistered = false; _ownershipStateInitialized = false; _wasOwner = false; _pendingReservations.Clear(); ActiveBarrels.Remove(this); } private void OnInventoryChanged() { if (!_sanitizingInventory) { EjectInvalidItems(); } } internal void EjectInvalidItems() { //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_nview == (Object)null || !_nview.IsValid() || !_nview.IsOwner() || _inventory == null) { return; } EnsureConfiguration(); List<ItemData> allItems = _inventory.GetAllItems(); if (allItems == null || allItems.Count == 0) { return; } List<ItemData> list = null; for (int i = 0; i < allItems.Count; i++) { ItemData val = allItems[i]; if (val != null && val.m_shared != null && !string.Equals(val.m_shared.m_name, _fuelItemName, StringComparison.Ordinal)) { if (list == null) { list = new List<ItemData>(); } list.Add(val); } } if (list == null) { return; } _sanitizingInventory = true; try { for (int j = 0; j < list.Count; j++) { ItemData val2 = list[j]; _inventory.RemoveItem(val2); ItemDrop.DropItem(val2, val2.m_stack, ((Component)this).transform.position + Vector3.up * 0.5f, ((Component)this).transform.rotation); } } finally { _sanitizingInventory = false; } LightMyFirePlugin.LogInvalidItemEjection(list.Count, ((Object)((Component)this).gameObject).name); } internal void SweepStaleReservations() { if (_pendingReservations.Count == 0 || (Object)(object)_nview == (Object)null || !_nview.IsValid() || !_nview.IsOwner()) { return; } float realtimeSinceStartup = Time.realtimeSinceStartup; if (realtimeSinceStartup < _nextReservationSweep) { return; } _nextReservationSweep = realtimeSinceStartup + 5f; long networkTicks = GetNetworkTicks(); List<long> list = null; foreach (KeyValuePair<long, PendingReservation> pendingReservation in _pendingReservations) { if (TimeSpan.FromTicks(Math.Max(0L, networkTicks - pendingReservation.Value.ReservedAtNetworkTicks)).TotalSeconds >= 30.0) { if (list == null) { list = new List<long>(); } list.Add(pendingReservation.Key); } } if (list == null) { return; } for (int i = 0; i < list.Count; i++) { long key = list[i]; if (_pendingReservations.TryGetValue(key, out var value)) { _pendingReservations.Remove(key); RefundLocally(value.Amount); } } PersistReservations(); } private static long GetNetworkTicks() { if (!((Object)(object)ZNet.instance == (Object)null)) { return ZNet.instance.GetTime().Ticks; } return DateTime.UtcNow.Ticks; } private void RefreshOwnershipState() { bool flag = (Object)(object)_nview != (Object)null && _nview.IsValid() && _nview.IsOwner(); if (!_ownershipStateInitialized || flag != _wasOwner) { _ownershipStateInitialized = true; _wasOwner = flag; _pendingReservations.Clear(); if (flag) { LoadPersistedReservations(); } } } private void LoadPersistedReservations() { //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_nview == (Object)null || !_nview.IsValid() || !_nview.IsOwner()) { return; } ZDO zDO = _nview.GetZDO(); if (zDO == null) { return; } string text = zDO.GetString("R4V9N1_LightMyFire_PendingReservations", string.Empty); if (string.IsNullOrEmpty(text)) { return; } string[] array = text.Split(new char[1] { ';' }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < array.Length; i++) { string[] array2 = array[i].Split(new char[1] { '|' }); if (array2.Length == 6 && long.TryParse(array2[0], NumberStyles.Integer, CultureInfo.InvariantCulture, out var result) && int.TryParse(array2[1], NumberStyles.Integer, CultureInfo.InvariantCulture, out var result2) && long.TryParse(array2[2], NumberStyles.Integer, CultureInfo.InvariantCulture, out var result3) && long.TryParse(array2[3], NumberStyles.Integer, CultureInfo.InvariantCulture, out var result4) && uint.TryParse(array2[4], NumberStyles.Integer, CultureInfo.InvariantCulture, out var result5) && long.TryParse(array2[5], NumberStyles.Integer, CultureInfo.InvariantCulture, out var result6) && result2 > 0 && result6 > 0) { _pendingReservations[result] = new PendingReservation { Amount = result2, RequesterPeer = result3, FireplaceId = new ZDOID(result4, result5), ReservedAtNetworkTicks = result6 }; } } } private void PersistReservations() { if ((Object)(object)_nview == (Object)null || !_nview.IsValid() || !_nview.IsOwner()) { return; } ZDO zDO = _nview.GetZDO(); if (zDO == null) { return; } if (_pendingReservations.Count == 0) { zDO.Set("R4V9N1_LightMyFire_PendingReservations", string.Empty); return; } StringBuilder stringBuilder = new StringBuilder(); foreach (KeyValuePair<long, PendingReservation> pendingReservation in _pendingReservations) { if (stringBuilder.Length > 0) { stringBuilder.Append(';'); } PendingReservation value = pendingReservation.Value; stringBuilder.Append(pendingReservation.Key.ToString(CultureInfo.InvariantCulture)).Append('|').Append(value.Amount.ToString(CultureInfo.InvariantCulture)) .Append('|') .Append(value.RequesterPeer.ToString(CultureInfo.InvariantCulture)) .Append('|') .Append(((ZDOID)(ref value.FireplaceId)).UserID.ToString(CultureInfo.InvariantCulture)) .Append('|') .Append(((ZDOID)(ref value.FireplaceId)).ID.ToString(CultureInfo.InvariantCulture)) .Append('|') .Append(value.ReservedAtNetworkTicks.ToString(CultureInfo.InvariantCulture)); } zDO.Set("R4V9N1_LightMyFire_PendingReservations", stringBuilder.ToString()); } private bool CanReceiveRequest(Vector3 targetPosition, float rangeSqr) { //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_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)this == (Object)null || !((Behaviour)this).isActiveAndEnabled) { return false; } if (!_runtimeInitialized && !TryInitializeRuntime()) { return false; } if ((Object)(object)_nview == (Object)null || !_nview.IsValid() || !_nview.HasOwner() || (Object)(object)_container == (Object)null) { return false; } Vector3 val = ((Component)this).transform.position - targetPosition; return ((Vector3)(ref val)).sqrMagnitude <= rangeSqr; } internal int GetFuelCount() { EnsureConfiguration(); if (_inventory == null && (Object)(object)_container != (Object)null) { _inventory = _container.GetInventory(); } if (_inventory != null) { return _inventory.CountItems(_fuelItemName, -1, false); } return 0; } private int RemoveFuelLocally(int requested) { if (requested <= 0 || _inventory == null) { return 0; } int num = _inventory.CountItems(_fuelItemName, -1, false); int num2 = Math.Min(num, requested); if (num2 <= 0) { return 0; } _inventory.RemoveItem(_fuelItemName, num2, -1, false); int num3 = _inventory.CountItems(_fuelItemName, -1, false); return Mathf.Clamp(num - num3, 0, num2); } private void RefundLocally(int amount) { //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) if (amount <= 0 || _inventory == null) { return; } EnsureConfiguration(); string fuelPrefabName = LightMyFirePlugin.GetFuelPrefabName(_fuelItemName); int num = _inventory.CountItems(_fuelItemName, -1, false); _inventory.AddItem(fuelPrefabName, amount, 1, 0, 0L, string.Empty, new Vector2i(-1, -1), false, false, false); int num2 = Mathf.Clamp(_inventory.CountItems(_fuelItemName, -1, false) - num, 0, amount); int num3 = amount - num2; if (num3 > 0) { GameObject val = (((Object)(object)ObjectDB.instance == (Object)null) ? null : ObjectDB.instance.GetItemPrefab(fuelPrefabName)); ItemDrop val2 = (((Object)(object)val == (Object)null) ? null : val.GetComponent<ItemDrop>()); if ((Object)(object)val2 != (Object)null && val2.m_itemData != null) { ItemData obj = val2.m_itemData.Clone(); obj.m_stack = num3; ItemDrop.DropItem(obj, num3, ((Component)this).transform.position + Vector3.up * 0.5f, ((Component)this).transform.rotation); } } } private void RPC_RequestFuel(long sender, long transactionId, ZDOID fireplaceId, int requestedAmount) { //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0074: 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_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: 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_0106: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) if (!LightMyFirePlugin.IsEnabled() || (Object)(object)_nview == (Object)null || !_nview.IsValid() || !_nview.IsOwner() || _inventory == null || _pendingReservations.ContainsKey(transactionId) || ZDOMan.instance == null) { return; } ZDO zDO = ZDOMan.instance.GetZDO(fireplaceId); if (zDO == null || zDO.GetOwner() != sender) { return; } float feedRange = LightMyFirePlugin.GetFeedRange(); Vector3 val = ((Component)this).transform.position - zDO.GetPosition(); if (((Vector3)(ref val)).sqrMagnitude > feedRange * feedRange) { return; } int num = Mathf.Clamp(requestedAmount, 0, 50); if (num > 0) { EnsureConfiguration(); int num2 = RemoveFuelLocally(num); if (num2 <= 0) { LightMyFireFeeder.SendGrant(transactionId, GetZdoId(), fireplaceId, 0); return; } _pendingReservations[transactionId] = new PendingReservation { Amount = num2, RequesterPeer = sender, FireplaceId = fireplaceId, ReservedAtNetworkTicks = GetNetworkTicks() }; PersistReservations(); LightMyFireFeeder.SendGrant(transactionId, GetZdoId(), fireplaceId, num2); } } private void RPC_AckApplied(long sender, long transactionId) { if (!((Object)(object)_nview == (Object)null) && _nview.IsValid() && _nview.IsOwner() && _pendingReservations.TryGetValue(transactionId, out var value) && sender == value.RequesterPeer) { _pendingReservations.Remove(transactionId); PersistReservations(); } } private void RPC_RefundFuel(long sender, long transactionId, int amount) { //IL_0054: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_nview == (Object)null) && _nview.IsValid() && _nview.IsOwner() && _pendingReservations.TryGetValue(transactionId, out var value)) { bool flag = sender == value.RequesterPeer; if (!flag && ZDOMan.instance != null) { ZDO zDO = ZDOMan.instance.GetZDO(value.FireplaceId); flag = zDO != null && zDO.GetOwner() == sender; } if (flag) { _pendingReservations.Remove(transactionId); int amount2 = Mathf.Clamp(amount, 0, value.Amount); RefundLocally(amount2); PersistReservations(); } } } internal ZDOID GetZdoId() { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) return (((Object)(object)_nview == (Object)null) ? null : _nview.GetZDO())?.m_uid ?? ZDOID.None; } internal bool SendRequestFuel(long transactionId, ZDOID fireplaceId, int requestedAmount) { //IL_0046: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_nview == (Object)null || !_nview.IsValid() || !_nview.HasOwner()) { return false; } _nview.InvokeRPC("R4V9N1_LightMyFire_RequestFuel", new object[3] { transactionId, fireplaceId, Mathf.Clamp(requestedAmount, 0, 50) }); return true; } internal void SendAckApplied(long transactionId) { if ((Object)(object)_nview != (Object)null && _nview.IsValid() && _nview.HasOwner()) { _nview.InvokeRPC("R4V9N1_LightMyFire_AckApplied", new object[1] { transactionId }); } } internal void SendRefundFuel(long transactionId, int amount) { if ((Object)(object)_nview != (Object)null && _nview.IsValid() && _nview.HasOwner() && amount > 0) { _nview.InvokeRPC("R4V9N1_LightMyFire_RefundFuel", new object[2] { transactionId, amount }); } } internal static LightMyFireBarrel FindByZdoId(ZDOID id) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) if (id == ZDOID.None) { return null; } for (int num = ActiveBarrels.Count - 1; num >= 0; num--) { LightMyFireBarrel lightMyFireBarrel = ActiveBarrels[num]; if ((Object)(object)lightMyFireBarrel == (Object)null) { ActiveBarrels.RemoveAt(num); } else if (lightMyFireBarrel.GetZdoId() == id) { return lightMyFireBarrel; } } return null; } internal static bool TryFindActiveMatchingBarrels(string fuelItemName, List<LightMyFireBarrel> results) { results.Clear(); for (int num = ActiveBarrels.Count - 1; num >= 0; num--) { LightMyFireBarrel lightMyFireBarrel = ActiveBarrels[num]; if ((Object)(object)lightMyFireBarrel == (Object)null) { ActiveBarrels.RemoveAt(num); } else { lightMyFireBarrel.EnsureConfiguration(); if (string.Equals(lightMyFireBarrel._fuelItemName, fuelItemName, StringComparison.Ordinal)) { results.Add(lightMyFireBarrel); } } } return results.Count > 0; } internal bool IsWithinRange(Vector3 targetPosition, float rangeSqr) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return CanReceiveRequest(targetPosition, rangeSqr); } internal static bool AnyActiveBarrels() { for (int num = ActiveBarrels.Count - 1; num >= 0; num--) { if ((Object)(object)ActiveBarrels[num] == (Object)null) { ActiveBarrels.RemoveAt(num); } } return ActiveBarrels.Count > 0; } internal static bool HasActiveBarrels() { for (int num = ActiveBarrels.Count - 1; num >= 0; num--) { if ((Object)(object)ActiveBarrels[num] == (Object)null) { ActiveBarrels.RemoveAt(num); } } if (ActiveBarrels.Count == 0) { LightMyFireBarrel[] array = Object.FindObjectsByType<LightMyFireBarrel>((FindObjectsInactive)0, (FindObjectsSortMode)0); foreach (LightMyFireBarrel lightMyFireBarrel in array) { if ((Object)(object)lightMyFireBarrel != (Object)null) { lightMyFireBarrel.TryInitializeRuntime(); } } } return ActiveBarrels.Count > 0; } internal static void TickMaintenance() { for (int num = ActiveBarrels.Count - 1; num >= 0; num--) { LightMyFireBarrel lightMyFireBarrel = ActiveBarrels[num]; if ((Object)(object)lightMyFireBarrel == (Object)null) { ActiveBarrels.RemoveAt(num); } else { lightMyFireBarrel.SweepStaleReservations(); } } } internal static void EjectInvalidItemsFromOwnedBarrels() { for (int num = ActiveBarrels.Count - 1; num >= 0; num--) { LightMyFireBarrel lightMyFireBarrel = ActiveBarrels[num]; if ((Object)(object)lightMyFireBarrel == (Object)null) { ActiveBarrels.RemoveAt(num); } else { lightMyFireBarrel.EjectInvalidItems(); } } } } internal static class LightMyFireFeeder { private struct OutboundState { public LightMyFireBarrel CurrentBarrel; public ZDOID FireplaceId; public int RemainingAmount; public List<LightMyFireBarrel> Candidates; public int NextCandidateIndex; public float SentAtRealtime; } private readonly struct BarrelDistance { public readonly LightMyFireBarrel Barrel; public readonly float DistanceSqr; public BarrelDistance(LightMyFireBarrel barrel, float distanceSqr) { Barrel = barrel; DistanceSqr = distanceSqr; } } internal const string RpcGrantFuel = "R4V9N1_LightMyFire_GrantFuel"; private const float OutboundRequestTimeoutSeconds = 20f; private static readonly Dictionary<long, OutboundState> PendingOutbound = new Dictionary<long, OutboundState>(); private static readonly List<OutboundState> DeferredSmelterRequests = new List<OutboundState>(); private static readonly HashSet<ZDOID> LightsAwaitingResponse = new HashSet<ZDOID>(); private const float SmelterDelaySeconds = 30f; private static float _smelterReleaseAt; private static readonly HashSet<ZDOID> FireplacesAwaitingResponse = new HashSet<ZDOID>(); private static long _txCounter; private const float SmelterFuelRetrySeconds = 10f; private static readonly Dictionary<ZDOID, float> NextSmelterFuelAttempt = new Dictionary<ZDOID, float>(); internal static void TickDeferred() { if (DeferredSmelterRequests.Count > 0 && Time.realtimeSinceStartup >= _smelterReleaseAt) { FlushDeferredSmelterRequests(); } } private static long NextTransactionId() { long uID = ZNet.GetUID(); _txCounter++; return (uID << 20) ^ (_txCounter & 0xFFFFF); } internal static void PruneStaleOutbound() { //IL_00ab: Unknown result type (might be due to invalid IL or missing references) if (PendingOutbound.Count == 0) { return; } float realtimeSinceStartup = Time.realtimeSinceStartup; List<long> list = null; foreach (KeyValuePair<long, OutboundState> item in PendingOutbound) { if (realtimeSinceStartup - item.Value.SentAtRealtime >= 20f) { if (list == null) { list = new List<long>(); } list.Add(item.Key); } } if (list == null) { return; } for (int i = 0; i < list.Count; i++) { if (PendingOutbound.TryGetValue(list[i], out var value)) { PendingOutbound.Remove(list[i]); if (!TrySendNextRequest(value)) { MarkResolved(value.FireplaceId); } } } } private static void MarkResolved(ZDOID targetId) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) FireplacesAwaitingResponse.Remove(targetId); LightsAwaitingResponse.Remove(targetId); FlushDeferredSmelterRequests(); } private static void FlushDeferredSmelterRequests() { //IL_004b: Unknown result type (might be due to invalid IL or missing references) if (LightsAwaitingResponse.Count > 0 || DeferredSmelterRequests.Count == 0 || Time.realtimeSinceStartup < _smelterReleaseAt) { return; } List<OutboundState> list = new List<OutboundState>(DeferredSmelterRequests); DeferredSmelterRequests.Clear(); for (int i = 0; i < list.Count; i++) { if (!FireplacesAwaitingResponse.Contains(list[i].FireplaceId)) { TrySendNextRequest(list[i]); } } } internal static void OnSmelterUpdate(Smelter smelter) { //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: 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_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00df: 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_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_021c: Unknown result type (might be due to invalid IL or missing references) //IL_021d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)smelter == (Object)null || smelter.m_maxFuel <= 0 || !LightMyFirePlugin.IsEnabled() || !LightMyFireBarrel.AnyActiveBarrels()) { return; } ZNetView smelterView = LightMyFireOreFeeder.GetSmelterView(smelter); if ((Object)(object)smelterView == (Object)null || !smelterView.IsValid() || !smelterView.IsOwner()) { return; } ZDO zDO = smelterView.GetZDO(); float num = zDO.GetFloat(ZDOVars.s_fuel, 0f); float num2 = Mathf.Max((float)smelter.m_maxFuel * 0.25f, (float)smelter.m_fuelPerProduct * 2f); ZDOID uid = zDO.m_uid; if (num > num2 || LightsAwaitingResponse.Count > 0 || FireplacesAwaitingResponse.Contains(uid) || (NextSmelterFuelAttempt.TryGetValue(uid, out var value) && Time.realtimeSinceStartup < value)) { return; } if (!string.Equals(LightMyFirePlugin.GetSupportedFuelItemName(smelter), "$item_coal", StringComparison.Ordinal)) { NextSmelterFuelAttempt[uid] = float.MaxValue; return; } NextSmelterFuelAttempt[uid] = Time.realtimeSinceStartup + 10f; int num3 = Mathf.FloorToInt((float)smelter.m_maxFuel - num + 0.001f); List<LightMyFireBarrel> list = new List<LightMyFireBarrel>(); if (num3 <= 0 || !LightMyFireBarrel.TryFindActiveMatchingBarrels("$item_coal", list)) { return; } float feedRange = LightMyFirePlugin.GetFeedRange(); Vector3 position = ((Component)smelter).transform.position; List<BarrelDistance> list2 = new List<BarrelDistance>(); for (int i = 0; i < list.Count; i++) { if (list[i].IsWithinRange(position, feedRange * feedRange)) { LightMyFireBarrel barrel = list[i]; Vector3 val = ((Component)list[i]).transform.position - position; list2.Add(new BarrelDistance(barrel, ((Vector3)(ref val)).sqrMagnitude)); } } if (list2.Count != 0) { list2.Sort(delegate(BarrelDistance left, BarrelDistance right) { float distanceSqr = left.DistanceSqr; return distanceSqr.CompareTo(right.DistanceSqr); }); List<LightMyFireBarrel> list3 = new List<LightMyFireBarrel>(list2.Count); for (int num4 = 0; num4 < list2.Count; num4++) { list3.Add(list2[num4].Barrel); } TrySendNextRequest(new OutboundState { CurrentBarrel = null, FireplaceId = uid, RemainingAmount = num3, Candidates = list3, NextCandidateIndex = 0, SentAtRealtime = 0f }); } } internal static void ScanAndRequestRefills() { //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_01df: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: Unknown result type (might be due to invalid IL or missing references) //IL_01ff: Unknown result type (might be due to invalid IL or missing references) //IL_0215: Unknown result type (might be due to invalid IL or missing references) //IL_021a: Unknown result type (might be due to invalid IL or missing references) //IL_021c: Unknown result type (might be due to invalid IL or missing references) //IL_0221: Unknown result type (might be due to invalid IL or missing references) //IL_02c8: 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) //IL_0310: Unknown result type (might be due to invalid IL or missing references) //IL_032e: Unknown result type (might be due to invalid IL or missing references) PruneStaleOutbound(); if (!LightMyFireBarrel.HasActiveBarrels()) { return; } Fireplace[] array = (Fireplace[])(((object)Object.FindObjectsByType<Fireplace>((FindObjectsInactive)0, (FindObjectsSortMode)0)) ?? ((object)new Fireplace[0])); Smelter[] array2 = (Smelter[])(((object)Object.FindObjectsByType<Smelter>((FindObjectsInactive)0, (FindObjectsSortMode)0)) ?? ((object)new Smelter[0])); CookingStation[] array3 = (CookingStation[])(((object)Object.FindObjectsByType<CookingStation>((FindObjectsInactive)0, (FindObjectsSortMode)0)) ?? ((object)new CookingStation[0])); DeferredSmelterRequests.Clear(); _smelterReleaseAt = Time.realtimeSinceStartup + 30f; if (array.Length == 0 && array2.Length == 0 && array3.Length == 0) { LightMyFirePlugin.LogScanSummary(0, 0, 0, 0, 0, 0); return; } List<Component> list = new List<Component>(array.Length + array2.Length + array3.Length); list.AddRange((IEnumerable<Component>)(object)array); list.AddRange((IEnumerable<Component>)(object)array2); list.AddRange((IEnumerable<Component>)(object)array3); int num = 0; int num2 = 0; int num3 = 0; int num4 = 0; int num5 = 0; float feedRange = LightMyFirePlugin.GetFeedRange(); float rangeSqr = feedRange * feedRange; List<LightMyFireBarrel> list2 = new List<LightMyFireBarrel>(); List<BarrelDistance> list3 = new List<BarrelDistance>(); for (int i = 0; i < list.Count; i++) { Component val = list[i]; bool flag = val is Fireplace; if ((Object)(object)val == (Object)null) { continue; } ZNetView val2 = ResolveNetworkView(val); if ((Object)(object)val2 == (Object)null || !val2.IsValid() || !val2.IsOwner()) { continue; } num++; ZDO zDO = val2.GetZDO(); if (zDO == null) { continue; } ZDOID uid = zDO.m_uid; if ((val is CookingStation && LightMyFireAutoFuelToggle.IsAutoFuelOff(zDO)) || FireplacesAwaitingResponse.Contains(uid) || !TryGetFuelInfo(val, out var fuelItemName, out var maxFuel)) { continue; } num2++; if (val is Smelter && LightMyFireOreFeeder.SmelterHookActive && string.Equals(fuelItemName, "$item_coal", StringComparison.Ordinal)) { continue; } float num6 = zDO.GetFloat(ZDOVars.s_fuel, 0f); int num7 = Mathf.FloorToInt(maxFuel - num6 + 0.001f); if (num7 <= 0) { continue; } num3++; if (!LightMyFireBarrel.TryFindActiveMatchingBarrels(fuelItemName, list2)) { continue; } Vector3 position = val.transform.position; list3.Clear(); for (int j = 0; j < list2.Count; j++) { LightMyFireBarrel lightMyFireBarrel = list2[j]; if (lightMyFireBarrel.IsWithinRange(position, rangeSqr)) { Vector3 val3 = ((Component)lightMyFireBarrel).transform.position - position; list3.Add(new BarrelDistance(lightMyFireBarrel, ((Vector3)(ref val3)).sqrMagnitude)); } } if (list3.Count == 0) { continue; } num4++; list3.Sort(delegate(BarrelDistance left, BarrelDistance right) { float distanceSqr = left.DistanceSqr; return distanceSqr.CompareTo(right.DistanceSqr); }); List<LightMyFireBarrel> list4 = new List<LightMyFireBarrel>(list3.Count); for (int num8 = 0; num8 < list3.Count; num8++) { list4.Add(list3[num8].Barrel); } OutboundState outboundState = new OutboundState { CurrentBarrel = null, FireplaceId = uid, RemainingAmount = num7, Candidates = list4, NextCandidateIndex = 0, SentAtRealtime = 0f }; if (!flag) { DeferredSmelterRequests.Add(outboundState); continue; } LightsAwaitingResponse.Add(uid); if (TrySendNextRequest(outboundState)) { num5++; } else { LightsAwaitingResponse.Remove(uid); } } FlushDeferredSmelterRequests(); LightMyFirePlugin.LogScanSummary(list.Count, num, num2, num3, num4, num5); } private static bool TrySendNextRequest(OutboundState state) { //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) if (state.Candidates == null || state.RemainingAmount <= 0) { return false; } while (state.NextCandidateIndex < state.Candidates.Count) { LightMyFireBarrel lightMyFireBarrel = state.Candidates[state.NextCandidateIndex]; state.NextCandidateIndex++; if (!((Object)(object)lightMyFireBarrel == (Object)null)) { int num = Mathf.Min(state.RemainingAmount, 50); if (num <= 0) { return false; } long num2 = NextTransactionId(); state.CurrentBarrel = lightMyFireBarrel; state.SentAtRealtime = Time.realtimeSinceStartup; PendingOutbound[num2] = state; FireplacesAwaitingResponse.Add(state.FireplaceId); if (lightMyFireBarrel.SendRequestFuel(num2, state.FireplaceId, num)) { return true; } PendingOutbound.Remove(num2); FireplacesAwaitingResponse.Remove(state.FireplaceId); } } return false; } internal static void SendGrant(long transactionId, ZDOID barrelId, ZDOID fireplaceId, int grantedAmount) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) if (ZRoutedRpc.instance == null || ZDOMan.instance == null) { return; } ZDO zDO = ZDOMan.instance.GetZDO(fireplaceId); if (zDO != null) { long owner = zDO.GetOwner(); if (owner != 0L) { ZRoutedRpc.instance.InvokeRoutedRPC(owner, "R4V9N1_LightMyFire_GrantFuel", new object[4] { transactionId, barrelId, fireplaceId, grantedAmount }); } } } internal static void RPC_GrantFuel(long sender, long transactionId, ZDOID barrelId, ZDOID fireplaceId, int grantedAmount) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_008a: 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) OutboundState value; bool num = PendingOutbound.TryGetValue(transactionId, out value); LightMyFireBarrel lightMyFireBarrel = (num ? value.CurrentBarrel : LightMyFireBarrel.FindByZdoId(barrelId)); if (!num) { if (grantedAmount > 0) { RefundToBarrel(lightMyFireBarrel, transactionId, grantedAmount); } return; } PendingOutbound.Remove(transactionId); if (grantedAmount <= 0) { if (!TrySendNextRequest(value)) { MarkResolved(value.FireplaceId); } return; } int num2 = TryApplyFuelToFireplace(fireplaceId, grantedAmount); int num3 = grantedAmount - num2; if (num3 > 0) { RefundToBarrel(lightMyFireBarrel, transactionId, num3); } else if ((Object)(object)lightMyFireBarrel != (Object)null) { lightMyFireBarrel.SendAckApplied(transactionId); } if (num2 <= 0 || num3 > 0) { MarkResolved(value.FireplaceId); return; } value.RemainingAmount = Math.Max(0, value.RemainingAmount - num2); if (value.RemainingAmount <= 0 || !TrySendNextRequest(value)) { MarkResolved(value.FireplaceId); } } private static void RefundToBarrel(LightMyFireBarrel barrel, long transactionId, int amount) { if ((Object)(object)barrel != (Object)null && amount > 0) { barrel.SendRefundFuel(transactionId, amount); } } private static int TryApplyFuelToFireplace(ZDOID fireplaceId, int grantedAmount) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)ZNetScene.instance == (Object)null) { return 0; } GameObject val = ZNetScene.instance.FindInstance(fireplaceId); if ((Object)(object)val == (Object)null) { return 0; } Component val2 = (Component)(object)val.GetComponent<Fireplace>(); if ((Object)(object)val2 == (Object)null) { val2 = (Component)(object)val.GetComponentInChildren<Fireplace>(true); } if ((Object)(object)val2 == (Object)null) { val2 = (Component)(object)val.GetComponent<Smelter>(); } if ((Object)(object)val2 == (Object)null) { val2 = (Component)(object)val.GetComponentInChildren<Smelter>(true); } if ((Object)(object)val2 == (Object)null) { val2 = (Component)(object)val.GetComponent<CookingStation>(); } if ((Object)(object)val2 == (Object)null) { val2 = (Component)(object)val.GetComponentInChildren<CookingStation>(true); } ZNetView val3 = ResolveNetworkView(val2); if ((Object)(object)val2 == (Object)null || (Object)(object)val3 == (Object)null || !val3.IsValid() || !val3.IsOwner() || !TryGetFuelInfo(val2, out var fuelItemName, out var maxFuel)) { return 0; } ZDO zDO = val3.GetZDO(); if (zDO == null || (val2 is CookingStation && LightMyFireAutoFuelToggle.IsAutoFuelOff(zDO))) { return 0; } float num = zDO.GetFloat(ZDOVars.s_fuel, 0f); int num2 = Mathf.Clamp(Mathf.FloorToInt(maxFuel - num + 0.001f), 0, 50); int num3 = Mathf.Min(grantedAmount, num2); if (num3 <= 0) { return 0; } zDO.Set(ZDOVars.s_fuel, Mathf.Clamp(num + (float)num3, 0f, maxFuel)); LightMyFirePlugin.LogTransfer(num3, fuelItemName, GetTargetDisplayName(val2)); return num3; } private static bool TryGetFuelInfo(Component target, out string fuelItemName, out float maxFuel) { fuelItemName = null; maxFuel = 0f; Fireplace val = (Fireplace)(object)((target is Fireplace) ? target : null); if ((Object)(object)val != (Object)null) { fuelItemName = LightMyFirePlugin.GetSupportedFuelItemName(val); maxFuel = val.m_maxFuel; return fuelItemName != null; } Smelter val2 = (Smelter)(object)((target is Smelter) ? target : null); if ((Object)(object)val2 != (Object)null) { fuelItemName = LightMyFirePlugin.GetSupportedFuelItemName(val2); maxFuel = val2.m_maxFuel; return fuelItemName != null; } CookingStation val3 = (CookingStation)(object)((target is CookingStation) ? target : null); if ((Object)(object)val3 != (Object)null) { fuelItemName = LightMyFirePlugin.GetSupportedFuelItemName(val3); maxFuel = val3.m_maxFuel; return fuelItemName != null; } return false; } private static string GetTargetDisplayName(Component target) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) Fireplace val = (Fireplace)(object)((target is Fireplace) ? target : null); if ((Object)(object)val != (Object)null) { return val.GetHoverName(); } string text = ((target is Smelter) ? ((Smelter)target).m_name : ((target is CookingStation) ? ((CookingStation)target).m_name : ((Object)target.gameObject).name)); if (Localization.instance == null) { return text; } return Localization.instance.Localize(text); } private static ZNetView ResolveNetworkView(Component fireplace) { if ((Object)(object)fireplace == (Object)null) { return null; } ZNetView component = fireplace.GetComponent<ZNetView>(); if ((Object)(object)component != (Object)null) { return component; } component = fireplace.GetComponentInParent<ZNetView>(); if ((Object)(object)component != (Object)null) { return component; } return fireplace.GetComponentInChildren<ZNetView>(true); } } internal static class LightMyFireItemFilter { private static readonly ConditionalWeakTable<Inventory, StrongBox<string>> FilteredInventories = new ConditionalWeakTable<Inventory, StrongBox<string>>(); internal static void RegisterFilteredInventory(Inventory inventory, string fuelItemName) { if (inventory != null && !string.IsNullOrEmpty(fuelItemName)) { if (FilteredInventories.TryGetValue(inventory, out var value)) { value.Value = fuelItemName; } else { FilteredInventories.Add(inventory, new StrongBox<string>(fuelItemName)); } } } internal static void UnregisterFilteredInventory(Inventory inventory) { if (inventory != null) { FilteredInventories.Remove(inventory); } } internal static bool TryGetExpectedFuel(Inventory inventory, out string fuelItemName) { fuelItemName = null; if (inventory == null) { return false; } if (!FilteredInventories.TryGetValue(inventory, out var value) || value == null || string.IsNullOrEmpty(value.Value)) { return false; } fuelItemName = value.Value; return true; } internal static bool IsRejected(Inventory inventory, ItemData item) { if (!TryGetExpectedFuel(inventory, out var fuelItemName) || item == null || item.m_shared == null) { return false; } return !IsAcceptedFuelName(fuelItemName, item.m_shared.m_name); } internal static bool IsRejectedInvocation(Inventory inventory, MethodBase method, object[] args, out string rejectedItemName, out string expectedFuelName) { rejectedItemName = null; expectedFuelName = null; if (!TryGetExpectedFuel(inventory, out expectedFuelName) || method == null || args == null) { return false; } ParameterInfo[] parameters = method.GetParameters(); foreach (object obj in args) { if (obj == null) { continue; } ItemData val = (ItemData)((obj is ItemData) ? obj : null); if (val != null && val.m_shared != null) { string name = val.m_shared.m_name; if (!IsAcceptedFuelName(expectedFuelName, name)) { rejectedItemName = name; return true; } continue; } ItemDrop val2 = (ItemDrop)((obj is ItemDrop) ? obj : null); if ((Object)(object)val2 != (Object)null && val2.m_itemData != null && val2.m_itemData.m_shared != null) { string name2 = val2.m_itemData.m_shared.m_name; if (!IsAcceptedFuelName(expectedFuelName, name2)) { rejectedItemName = name2; return true; } continue; } GameObject val3 = (GameObject)((obj is GameObject) ? obj : null); if (!((Object)(object)val3 != (Object)null)) { continue; } ItemDrop component = val3.GetComponent<ItemDrop>(); if ((Object)(object)component != (Object)null && component.m_itemData != null && component.m_itemData.m_shared != null) { string name3 = component.m_itemData.m_shared.m_name; if (!IsAcceptedFuelName(expectedFuelName, name3)) { rejectedItemName = name3; return true; } } } if (string.Equals(method.Name, "AddItem", StringComparison.Ordinal) || string.Equals(method.Name, "CanAddItem", StringComparison.Ordinal)) { int num = Math.Min(parameters.Length, args.Length); for (int j = 0; j < num; j++) { if (parameters[j].ParameterType != typeof(string) || !(args[j] is string)) { continue; } string text = (parameters[j].Name ?? string.Empty).ToLowerInvariant(); if (!text.Contains("crafter") && !text.Contains("player") && !text.Contains("creator") && (text == "name" || text.Contains("item") || text.Contains("prefab") || text.Contains("shared"))) { string text2 = (string)args[j]; if (IsAcceptedFuelName(expectedFuelName, text2)) { break; } rejectedItemName = text2; return true; } } } if (IsBulkMoveMethod(method.Name)) { foreach (object obj2 in args) { Inventory val4 = (Inventory)((obj2 is Inventory) ? obj2 : null); if (val4 == null || val4 == inventory) { continue; } List<ItemData> allItems = val4.GetAllItems(); if (allItems == null) { continue; } for (int l = 0; l < allItems.Count; l++) { ItemData val5 = allItems[l]; if (val5 != null && val5.m_shared != null) { string name4 = val5.m_shared.m_name; if (!IsAcceptedFuelName(expectedFuelName, name4)) { rejectedItemName = name4; return true; } } } } } return false; } private static bool IsBulkMoveMethod(string methodName) { if (!string.Equals(methodName, "MoveAll", StringComparison.Ordinal) && !string.Equals(methodName, "MoveInventoryToThis", StringComparison.Ordinal)) { return string.Equals(methodName, "MoveAllToThis", StringComparison.Ordinal); } return true; } internal static bool IsAcceptedFuelName(string expectedFuelName, string actualItemName) { if (string.IsNullOrEmpty(expectedFuelName) || string.IsNullOrEmpty(actualItemName)) { return false; } if (string.Equals(expectedFuelName, actualItemName, StringComparison.Ordinal)) { return true; } if (string.Equals(expectedFuelName, "R4V9N1_LightMyFire_Ore", StringComparison.Ordinal)) { return LightMyFirePlugin.IsSmeltableOreName(actualItemName); } if (string.Equals(expectedFuelName, "$item_coal", StringComparison.Ordinal)) { return string.Equals(actualItemName, "Coal", StringComparison.OrdinalIgnoreCase); } if (string.Equals(expectedFuelName, "$item_resin", StringComparison.Ordinal)) { return string.Equals(actualItemName, "Resin", StringComparison.OrdinalIgnoreCase); } if (string.Equals(expectedFuelName, "$item_wood", StringComparison.Ordinal)) { return string.Equals(actualItemName, "Wood", StringComparison.OrdinalIgnoreCase); } return false; } } internal static class LightMyFireHarmonyPatches { private static class InventoryItemGatePatch { public static bool Prefix(Inventory __instance, MethodBase __originalMethod, object[] __args) { if (!LightMyFireItemFilter.IsRejectedInvocation(__instance, __originalMethod, __args, out var rejectedItemName, out var expectedFuelName)) { return true; } LightMyFirePlugin.LogRejectedInsertion(expectedFuelName, rejectedItemName, (__originalMethod == null) ? "Inventory" : __originalMethod.Name); return false; } } private static Harmony _harmony; internal static void Apply(ManualLogSource log) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Expected O, but got Unknown _harmony = new Harmony("r4v9n1.lightmyfire"); PatchCurrentInventoryEntryPoints(log); _harmony.CreateClassProcessor(typeof(CookingStationAutoFuelInteractPatch)).Patch(); _harmony.CreateClassProcessor(typeof(CookingStationAutoFuelHoverPatch)).Patch(); _harmony.CreateClassProcessor(typeof(FuelBarrelStackAllPatch)).Patch(); try { _harmony.CreateClassProcessor(typeof(SmelterOreFeedPatch)).Patch(); LightMyFireOreFeeder.SmelterHookActive = true; log.LogInfo((object)"[LightMyFire] Ore Chests feed smelters from Smelter.UpdateSmelter (once per second, owner only)."); } catch (Exception ex) { log.LogWarning((object)("[LightMyFire] Could not hook Smelter.UpdateSmelter (" + ex.Message + "); Ore Chests fall back to a once-a-minute refill.")); } InventoryLinkWoodBarrelCompat.TryPatch(_harmony, log); } internal static void Unpatch() { if (_harmony != null) { _harmony.UnpatchSelf(); _harmony = null; } } private static void PatchCurrentInventoryEntryPoints(ManualLogSource log) { //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Expected O, but got Unknown int num = 0; HashSet<MethodBase> hashSet = new HashSet<MethodBase>(); List<MethodInfo> declaredMethods = AccessTools.GetDeclaredMethods(typeof(Inventory)); for (int i = 0; i < declaredMethods.Count; i++) { MethodInfo methodInfo = declaredMethods[i]; if (methodInfo == null || hashSet.Contains(methodInfo) || !IsInsertionOrCheckMethod(methodInfo.Name)) { continue; } ParameterInfo[] parameters = methodInfo.GetParameters(); bool flag = false; for (int j = 0; j < parameters.Length; j++) { Type parameterType = parameters[j].ParameterType; if (typeof(ItemData).IsAssignableFrom(parameterType) || typeof(ItemDrop).IsAssignableFrom(parameterType) || typeof(GameObject).IsAssignableFrom(parameterType) || parameterType == typeof(string) || (IsBulkMoveMethod(methodInfo.Name) && typeof(Inventory).IsAssignableFrom(parameterType))) { flag = true; break; } } if (flag) { try { _harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(InventoryItemGatePatch), "Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); hashSet.Add(methodInfo); num++; } catch (Exception ex) { log.LogWarning((object)("[LightMyFire] Could not patch current Inventory method " + Describe(methodInfo) + ": " + ex.Message)); } } } if (num > 0) { log.LogInfo((object)("[LightMyFire] Strict fuel-only item filter attached to " + num + " current Inventory insertion/check method(s).")); } else { log.LogWarning((object)"[LightMyFire] No compatible Inventory insertion methods were found to patch. Owner-side barrel sanitation remains active as a safety net."); } } private static bool IsInsertionOrCheckMethod(string methodName) { if (!string.Equals(methodName, "AddItem", StringComparison.Ordinal) && !string.Equals(methodName, "CanAddItem", StringComparison.Ordinal) && !string.Equals(methodName, "MoveItemToThis", StringComparison.Ordinal)) { return IsBulkMoveMethod(methodName); } return true; } private static bool IsBulkMoveMethod(string methodName) { if (!string.Equals(methodName, "MoveAll", StringComparison.Ordinal) && !string.Equals(methodName, "MoveInventoryToThis", StringComparison.Ordinal)) { return string.Equals(methodName, "MoveAllToThis", StringComparison.Ordinal); } return true; } private static string Describe(MethodInfo method) { ParameterInfo[] parameters = method.GetParameters(); string[] array = new string[parameters.Length]; for (int i = 0; i < parameters.Length; i++) { array[i] = parameters[i].ParameterType.Name; } return method.Name + "(" + string.Join(", ", array) + ")"; } } public sealed class LightMyFireOreChest : MonoBehaviour { private struct PendingReservation { public int Amount; public string ItemPrefabName; public long RequesterPeer; public ZDOID SmelterId; public long ReservedAtNetworkTicks; } private const string RpcRequestOre = "R4V9N1_LightMyFire_RequestOre"; private const string RpcAckOre = "R4V9N1_LightMyFire_AckOre"; private const string RpcRefundOre = "R4V9N1_LightMyFire_RefundOre"; internal const int MaxRequestPerTransaction = 50; private const float ReservationTimeoutSeconds = 30f; private const string ReservationStateZdoKey = "R4V9N1_LightMyFire_PendingOreReservations"; private static readonly List<LightMyFireOreChest> ActiveChests = new List<LightMyFireOreChest>(); private ZNetView _nview; private Container _container; private Inventory _inventory; private bool _rpcRegistered; private bool _inventoryHooksRegistered; private bool _runtimeInitialized; private bool _sanitizingInventory; private bool _ownershipStateInitialized; private bool _wasOwner; private readonly Dictionary<long, PendingReservation> _pendingReservations = new Dictionary<long, PendingReservation>(); private float _nextReservationSweep; private void Awake() { _nview = ((Component)this).GetComponent<ZNetView>(); _container = ((Component)this).GetComponent<Container>(); } private void Start() { TryInitializeRuntime(); } private void Update() { if (!_runtimeInitialized) { TryInitializeRuntime(); } else { RefreshOwnershipState(); } } private bool TryInitializeRuntime() { if ((Object)(object)_nview == (Object)null) { _nview = ((Component)this).GetComponent<ZNetView>(); } if ((Object)(object)_container == (Object)null) { _container = ((Component)this).GetComponent<Container>(); } if ((Object)(object)_container == (Object)null) { return false; } if (_inventory == null) { _inventory = _container.GetInventory(); } if (_inventory != null && !_inventoryHooksRegistered) { Inventory inventory = _inventory; inventory.m_onChanged = (Action)Delegate.Combine(inventory.m_onChanged, new Action(OnInventoryChanged)); LightMyFireItemFilter.RegisterFilteredInventory(_inventory, "R4V9N1_LightMyFire_Ore"); _inventoryHooksRegistered = true; } if ((Object)(object)_nview == (Object)null || !_nview.IsValid() || _nview.GetZDO() == null || _inventory == null) { return false; } if (!_rpcRegistered) { _nview.Register<long, ZDOID, int, string>("R4V9N1_LightMyFire_RequestOre", (Method<long, ZDOID, int, string>)RPC_RequestOre); _nview.Register<long>("R4V9N1_LightMyFire_AckOre", (Action<long, long>)RPC_AckOre); _nview.Register<long, int>("R4V9N1_LightMyFire_RefundOre", (Action<long, long, int>)RPC_RefundOre); _rpcRegistered = true; } if (!ActiveChests.Contains(this)) { ActiveChests.Add(this); } RefreshOwnershipState(); _runtimeInitialized = true; LightMyFirePlugin.LogOreChestRuntimeReady(((Object)((Component)this).gameObject).name); return true; } private void OnDestroy() { if (_inventory != null && _inventoryHooksRegistered) { Inventory inventory = _inventory; inventory.m_onChanged = (Action)Delegate.Remove(inventory.m_onChanged, new Action(OnInventoryChanged)); LightMyFireItemFilter.UnregisterFilteredInventory(_inventory); _inventoryHooksRegistered = false; } _inventory = null; _runtimeInitialized = false; _rpcRegistered = false; _ownershipStateInitialized = false; _wasOwner = false; _pendingReservations.Clear(); ActiveChests.Remove(this); } private void OnInventoryChanged() { if (!_sanitizingInventory) { EjectInvalidItems(); } } internal void EjectInvalidItems() { //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_nview == (Object)null || !_nview.IsValid() || !_nview.IsOwner() || _inventory == null || !LightMyFirePlugin.IsSmeltableOreListReady()) { return; } List<ItemData> allItems = _inventory.GetAllItems(); if (allItems == null || allItems.Count == 0) { return; } List<ItemData> list = null; for (int i = 0; i < allItems.Count; i++) { ItemData val = allItems[i]; if (val != null && val.m_shared != null && !LightMyFirePlugin.IsSmeltableOreName(val.m_shared.m_name)) { if (list == null) { list = new List<ItemData>(); } list.Add(val); } } if (list == null) { return; } _sanitizingInventory = true; try { for (int j = 0; j < list.Count; j++) { ItemData val2 = list[j]; _inventory.RemoveItem(val2); ItemDrop.DropItem(val2, val2.m_stack, ((Component)this).transform.position + Vector3.up * 0.5f, ((Component)this).transform.rotation); } } finally { _sanitizingInventory = false; } LightMyFirePlugin.LogInvalidItemEjection(list.Count, ((Object)((Component)this).gameObject).name); } internal void SweepStaleReservations() { if (_pendingReservations.Count == 0 || (Object)(object)_nview == (Object)null || !_nview.IsValid() || !_nview.IsOwner()) { return; } float realtimeSinceStartup = Time.realtimeSinceStartup; if (realtimeSinceStartup < _nextReservationSweep) { return; } _nextReservationSweep = realtimeSinceStartup + 5f; long networkTicks = GetNetworkTicks(); List<long> list = null; foreach (KeyValuePair<long, PendingReservation> pendingReservation in _pendingReservations) { if (TimeSpan.FromTicks(Math.Max(0L, networkTicks - pendingReservation.Value.ReservedAtNetworkTicks)).TotalSeconds >= 30.0) { if (list == null) { list = new List<long>(); } list.Add(pendingReservation.Key); } } if (list == null) { return; } for (int i = 0; i < list.Count; i++) { if (_pendingReservations.TryGetValue(list[i], out var value)) { _pendingReservations.Remove(list[i]); RefundLocally(value.ItemPrefabName, value.Amount); } } PersistReservations(); } private static long GetNetworkTicks() { if (!((Object)(object)ZNet.instance == (Object)null)) { return ZNet.instance.GetTime().Ticks; } return DateTime.UtcNow.Ticks; } private void RefreshOwnershipState() { bool flag = (Object)(object)_nview != (Object)null && _nview.IsValid() && _nview.IsOwner(); if (!_ownershipStateInitialized || flag != _wasOwner) { _ownershipStateInitialized = true; _wasOwner = flag; _pendingReservations.Clear(); if (flag) { LoadPersistedReservations(); } } } private void LoadPersistedReservations() { //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) ZDO val = (((Object)(object)_nview == (Object)null || !_nview.IsValid() || !_nview.IsOwner()) ? null : _nview.GetZDO()); if (val == null) { return; } string text = val.GetString("R4V9N1_LightMyFire_PendingOreReservations", string.Empty); if (string.IsNullOrEmpty(text)) { return; } string[] array = text.Split(new char[1] { ';' }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < array.Length; i++) { string[] array2 = array[i].Split(new char[1] { '|' }); if (array2.Length == 7 && long.TryParse(array2[0], NumberStyles.Integer, CultureInfo.InvariantCulture, out var result) && int.TryParse(array2[1], NumberStyles.Integer, CultureInfo.InvariantCulture, out var result2) && !string.IsNullOrEmpty(array2[2]) && long.TryParse(array2[3], NumberStyles.Integer, CultureInfo.InvariantCulture, out var result3) && long.TryParse(array2[4], NumberStyles.Integer, CultureInfo.InvariantCulture, out var result4) && uint.TryParse(array2[5], NumberStyles.Integer, CultureInfo.InvariantCulture, out var result5) && long.TryParse(array2[6], NumberStyles.Integer, CultureInfo.InvariantCulture, out var result6) && result2 > 0 && result6 > 0) { _pendingReservations[result] = new PendingReservation { Amount = result2, ItemPrefabName = array2[2], RequesterPeer = result3, SmelterId = new ZDOID(result4, result5), ReservedAtNetworkTicks = result6 }; } } } private void PersistReservations() { ZDO val = (((Object)(object)_nview == (Object)null || !_nview.IsValid() || !_nview.IsOwner()) ? null : _nview.GetZDO()); if (val == null) { return; } if (_pendingReservations.Count == 0) { val.Set("R4V9N1_LightMyFire_PendingOreReservations", string.Empty); return; } StringBuilder stringBuilder = new StringBuilder(); foreach (KeyValuePair<long, PendingReservation> pendingReservation in _pendingReservations) { if (stringBuilder.Length > 0) { stringBuilder.Append(';'); } PendingReservation value = pendingReservation.Value; stringBuilder.Append(pendingReservation.Key.ToString(CultureInfo.InvariantCulture)).Append('|').Append(value.Amount.ToString(CultureInfo.InvariantCulture)) .Append('|') .Append(value.ItemPrefabName) .Append('|') .Append(value.RequesterPeer.ToString(CultureInfo.InvariantCulture)) .Append('|') .Append(((ZDOID)(ref value.SmelterId)).UserID.ToString(CultureInfo.InvariantCulture)) .Append('|') .Append(((ZDOID)(ref value.SmelterId)).ID.ToString(CultureInfo.InvariantCulture)) .Append('|') .Append(value.ReservedAtNetworkTicks.ToString(CultureInfo.InvariantCulture)); } val.Set("R4V9N1_LightMyFire_PendingOreReservations", stringBuilder.ToString()); } private int RemoveOreLocally(HashSet<string> acceptedPrefabNames, int requested, out string itemPrefabName, out bool cheated) { itemPrefabName = null; cheated = false; if (requested <= 0 || _inventory == null) { return 0; } List<ItemData> allItems = _inventory.GetAllItems(); ItemData val = null; for (int i = 0; i < allItems.Count; i++) { ItemData val2 = allItems[i]; if (val2 != null && val2.m_shared != null && !((Object)(object)val2.m_dropPrefab == (Object)null) && acceptedPrefabNames.Contains(((Object)val2.m_dropPrefab).name) && (val == null || val2.m_gridPos.y < val.m_gridPos.y || (val2.m_gridPos.y == val.m_gridPos.y && val2.m_gridPos.x < val.m_gridPos.x))) { val = val2; } } if (val == null) { return 0; } string name = val.m_shared.m_name; itemPrefabName = ((Object)val.m_dropPrefab).name; for (int j = 0; j < allItems.Count; j++) { ItemData val3 = allItems[j]; if (val3 != null && val3.m_shared != null && val3.m_cheated && string.Equals(val3.m_shared.m_name, name, StringComparison.Ordinal)) { cheated = true; break; } } int num = _inventory.CountItems(name, -1, false); int num2 = Math.Min(num, requested); if (num2 <= 0) { return 0; } _inventory.RemoveItem(name, num2, -1, false); int num3 = _inventory.CountItems(name, -1, false); return Mathf.Clamp(num - num3, 0, num2); } private void RefundLocally(string itemPrefabName, int amount) { //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) if (amount <= 0 || _inventory == null || string.IsNullOrEmpty(itemPrefabName)) { return; } GameObject val = (((Object)(object)ObjectDB.instance == (Object)null) ? null : ObjectDB.instance.GetItemPrefab(itemPrefabName)); ItemDrop val2 = (((Object)(object)val == (Object)null) ? null : val.GetComponent<ItemDrop>()); if (!((Object)(object)val2 == (Object)null) && val2.m_itemData != null && val2.m_itemData.m_shared != null) { string name = val2.m_itemData.m_shared.m_name; int num = _inventory.CountItems(name, -1, false); _inventory.AddItem(itemPrefabName, amount, 1, 0, 0L, string.Empty, new Vector2i(-1, -1), false, false, false); int num2 = _inventory.CountItems(name, -1, false); int num3 = amount - Mathf.Clamp(num2 - num, 0, amount); if (num3 > 0) { ItemData obj = val2.m_itemData.Clone(); obj.m_stack = num3; ItemDrop.DropItem(obj, num3, ((Component)this).transform.position + Vector3.up * 0.5f, ((Component)this).transform.rotation); } } } private void RPC_RequestOre(long sender, long transactionId, ZDOID smelterId, int requestedAmount, string acceptedPrefabNames) { //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_024e: Unknown result type (might be due to invalid IL or missing references) //IL_024f: Unknown result type (might be due to invalid IL or missing references) //IL_026f: Unknown result type (might be due to invalid IL or missing references) //IL_0274: Unknown result type (might be due to invalid IL or missing references) //IL_0210: Unknown result type (might be due to invalid IL or missing references) //IL_0215: Unknown result type (might be due to invalid IL or missing references) if (!LightMyFirePlugin.IsEnabled() || (Object)(object)_nview == (Object)null || !_nview.IsValid() || !_nview.IsOwner() || _inventory == null || ZDOMan.instance == null || _pendingReservations.ContainsKey(transactionId)) { LightMyFirePlugin.LogOreDiagnostic("Ore request ignored by '" + ((Object)((Component)this).gameObject).name + "': disabled, not the owner, or a duplicate."); return; } ZDO zDO = ZDOMan.instance.GetZDO(smelterId); if (zDO == null || zDO.GetOwner() != sender) { LightMyFirePlugin.LogOreDiagnostic("Ore request ignored: the asking peer " + sender + " does not own that smelter (owner " + ((zDO == null) ? "unknown" : zDO.GetOwner().ToString(CultureInfo.InvariantCulture)) + ")."); return; } float oreFeedRange = LightMyFirePlugin.GetOreFeedRange(); Vector3 val = ((Component)this).transform.position - zDO.GetPosition(); if (((Vector3)(ref val)).sqrMagnitude > oreFeedRange * oreFeedRange) { LightMyFirePlugin.LogOreDiagnostic("Ore request ignored: the smelter is farther than " + oreFeedRange.ToString("0.#", CultureInfo.InvariantCulture) + " m."); return; } int num = Mathf.Clamp(requestedAmount, 0, 50); HashSet<string> hashSet = ParseAccepted(acceptedPrefabNames); string itemPrefabName = null; bool cheated = false; int num2 = ((num > 0 && hashSet.Count != 0) ? RemoveOreLocally(hashSet, num, out itemPrefabName, out cheated) : 0); LightMyFirePlugin.LogOreDiagnostic("Ore Chest '" + ((Object)((Component)this).gameObject).name + "' holds " + _inventory.GetAllItems().Count + " stack(s); granting " + num2 + " " + (itemPrefabName ?? "(nothing)") + " for request of " + num + " (accepted: " + hashSet.Count + " type(s))."); if (num2 <= 0) { LightMyFireOreFeeder.SendGrant(transactionId, GetZdoId(), smelterId, string.Empty, 0, cheated: false); return; } _pendingReservations[transactionId] = new PendingReservation { Amount = num2, ItemPrefabName = itemPrefabName, RequesterPeer = sender, SmelterId = smelterId, ReservedAtNetworkTicks = GetNetworkTicks() }; PersistReservations(); LightMyFireOreFeeder.SendGrant(transactionId, GetZdoId(), smelterId, itemPrefabName, num2, cheated); } private static HashSet<string> ParseAccepted(string acceptedPrefabNames) { HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal); if (string.IsNullOrEmpty(acceptedPrefabNames)) { return hashSet; } string[] array = acceptedPrefabNames.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < array.Length; i++) { if (LightMyFirePlugin.IsSmeltableOreName(array[i])) { hashSet.Add(array[i]); } } return hashSet; } private void RPC_AckOre(long sender, long transactionId) { if (!((Object)(object)_nview == (Object)null) && _nview.IsValid() && _nview.IsOwner() && _pendingReservations.TryGetValue(transactionId, out var value) && sender == value.RequesterPeer) { _pendingReservations.Remove(transactionId); PersistReservations(); } } private void RPC_RefundOre(long sender, long transactionId, int amount) { //IL_0054: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_nview == (Object)null) && _nview.IsValid() && _nview.IsOwner() && _pendingReservations.TryGetValue(transactionId, out var value)) { bool flag = sender == value.RequesterPeer; if (!flag && ZDOMan.instance != null) { ZDO zDO = ZDOMan.instance.GetZDO(value.SmelterId); flag = zDO != null && zDO.GetOwner() == sender; } if (flag) { _pendingReservations.Remove(transactionId); RefundLocally(value.ItemPrefabName, Mathf.Clamp(amount, 0, value.Amount)); PersistReservations(); } } } internal ZDOID GetZdoId() { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) return (((Object)(object)_nview == (Object)null) ? null : _nview.GetZDO())?.m_uid ?? ZDOID.None; } internal bool SendRequestOre(long transactionId, ZDOID smelterId, int requestedAmount, string acceptedPrefabNames) { //IL_0046: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_nview == (Object)null || !_nview.IsValid() || !_nview.HasOwner()) { return false; } _nview.InvokeRPC("R4V9N1_LightMyFire_RequestOre", new object[4] { transactionId, smelterId, Mathf.Clamp(requestedAmount, 0, 50), acceptedPrefabNames ?? string.Empty }); return true; } internal void SendAckOre(long transactionId) { if ((Object)(object)_nview != (Object)null && _nview.IsValid() && _nview.HasOwner()) { _nview.InvokeRPC("R4V9N1_LightMyFire_AckOre", new object[1] { transactionId }); } } internal void SendRefundOre(long transactionId, int amount) { if ((Object)(object)_nview != (Object)null && _nview.IsValid() && _nview.HasOwner() && amount > 0) { _nview.InvokeRPC("R4V9N1_LightMyFire_RefundOre", new object[2] { transactionId, amount }); } } internal bool IsReadyWithinRange(Vector3 targetPosition, float rangeSqr) { //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)this == (Object)null || !((Behaviour)this).isActiveAndEnabled || (!_runtimeInitialized && !TryInitializeRuntime())) { return false; } if ((Object)(object)_nview != (Object)null && _nview.IsValid() && _nview.HasOwner() && (Object)(object)_container != (Object)null) { Vector3 val = ((Component)this).transform.position - targetPosition; return ((Vector3)(ref val)).sqrMagnitude <= rangeSqr; } return false; } internal static LightMyFireOreChest FindByZdoId(ZDOID id) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) if (id == ZDOID.None) { return null; } for (int num = ActiveChests.Count - 1; num >= 0; num--) { LightMyFireOreChest lightMyFireOreChest = ActiveChests[num]; if ((Object)(object)lightMyFireOreChest == (Object)null) { ActiveChests.RemoveAt(num); } else if (lightMyFireOreChest.GetZdoId() == id) { return lightMyFireOreChest; } } return null; } internal static void GetActiveChests(List<LightMyFireOreChest> results) { results.Clear(); for (int num = ActiveChests.Count - 1; num >= 0; num--) { if ((Object)(object)ActiveChests[num] == (Object)null) { ActiveChests.RemoveAt(num); } else { results.Add(ActiveChests[num]); } } } internal static bool AnyActiveChests() { for (int num = ActiveChests.Count - 1; num >= 0; num--) { if ((Object)(object)ActiveChests[num] == (Object)null) { ActiveChests.RemoveAt(num); } } return ActiveChests.Count > 0; } internal static bool HasActiveChests() { for (int num = ActiveChests.Count - 1; num >= 0; num--) { if ((Object)(object)ActiveChests[num] == (Object)null) { ActiveChests.RemoveAt(num); } } if (ActiveChests.Count == 0) { LightMyFireOreChest[] array = Object.FindObjectsByType<LightMyFireOreChest>((FindObjectsInactive)0, (FindObjectsSortMode)0); for (int i = 0; i < array.Length; i++) { if ((Object)(object)array[i] != (Object)null) { array[i].TryInitializeRuntime(); } } } return ActiveChests.Count > 0; } internal static void TickMaintenance() { for (int num = ActiveChests.Count - 1; num >= 0; num--) { LightMyFireOreChest lightMyFireOreChest = ActiveChests[num]; if ((Object)(object)lightMyFireOreChest == (Object)null) { ActiveChests.RemoveAt(num); } else { lightMyFireOreChest.SweepStaleReservations(); lightMyFireOreChest.EjectInvalidItems(); } } } } internal static class LightMyFireOreFeeder { private sealed class OutboundState { public LightMyFireOreChest CurrentChest; public ZDOID SmelterId; public int RemainingAmount; public int AppliedAmount; public string AcceptedPrefabNames; public List<LightMyFireOreChest> Candidates; public int NextCandidateIndex; public float SentAtRealtime; } internal const string RpcGrantOre = "R4V9N1_LightMyFire_GrantOre"; private const float OutboundRequestTimeoutSeconds = 20f; private const float EmptyRetrySeconds = 5f; private const int RefillAtOrBelow = 2; private static readonly MethodInfo QueueOreMethod = AccessTools.Method(typeof(Smelter), "QueueOre", new Type[2] { typeof(string), typeof(bool) }, (Type[])null); private static readonly MethodInfo IsItemAllowedMethod = AccessTools.Method(typeof(Smelter), "IsItemAllowed", new Type[1] { typeof(string) }, (Type[])null); private static readonly FieldRef<Smelter, ZNetView> SmelterView = AccessTools.FieldRefAccess<Smelter, ZNetView>("m_nview"); internal static bool SmelterHookActive; private static readonly Dictionary<long, OutboundState> PendingOutbound = new Dictionary<long, OutboundState>(); private static readonly HashSet<ZDOID> SmeltersAwaitingResponse = new HashSet<ZDOID>(); private static readonly Dictionary<ZDOID, float> NextAttempt = new Dictionary<ZDOID, float>(); private static readonly Dictionary<ZDOID, float> NextStatusLog = new Dictionary<ZDOID, float>(); private static readonly List<LightMyFireOreChest> ChestBuffer = new List<LightMyFireOreChest>(); private static long _txCounter; private static bool _warnedMissingQueueOre; internal static ZNetView GetSmelterView(Smelter smelter) { if (!((Object)(object)smelter == (Object)null)) { return SmelterView.Invoke(smelter); } return null; } private static long NextTransactionId() { long uID = ZNet.GetUID(); _txCounter++; return (uID << 20) ^ (0x80000 | (_txCounter & 0x7FFFF)); } internal static void OnSmelterUpdate(Smelter smelter) { //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)smelter == (Object)null || smelter.m_maxOre <= 0 || !LightMyFirePlugin.IsEnabled() || !LightMyFireOreChest.AnyActiveChests()) { return; } ZNetView val = SmelterView.Invoke(smelter); if ((Object)(object)val == (Object)null || !val.IsValid() || !val.IsOwner()) { return; } ZDO zDO = val.GetZDO(); int num = zDO.GetInt(ZDOVars.s_queued, 0); int num2 = smelter.m_maxOre - num; ZDOID uid = zDO.m_uid; bool flag = SmeltersAwaitingResponse.Contains(uid); float value; bool flag2 = NextAttempt.TryGetValue(uid, out value) && Time.realtimeSinceStartup < value; if (num2 <= 0 || num > 2 || flag || flag2) { if (LightMyFirePlugin.IsDiagnosticsEnabled()) { LogStatus(smelter, uid, num, flag, flag2 ? (value - Time.realtimeSinceStartup) : 0f); } } else if (!string.Equals(LightMyFirePlugin.GetSupportedFuelItemName(smelter), "$item_coal", StringComparison.Ordinal)) { NextAttempt[uid] = float.MaxValue; } else if (QueueOreMethod == null || IsItemAllowedMethod == null) { if (!_warnedMissingQueueOre) { _warnedMissingQueueOre = true; LightMyFirePlugin.LogWarning("Valheim's Smelter.QueueOre/IsItemAllowed were not found; the Ore Chest cannot feed smelters in this game version."); } } else { StartRequest(smelter, uid, num2); } } private static void LogStatus(Smelter smelter, ZDOID id, int queued, bool awaiting, float cooldownLeft) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) float realtimeSinceStartup = Time.realtimeSinceStartup; if (!NextStatusLog.TryGetValue(id, out var value) || !(realtimeSinceStartup < value)) { NextStatusLog[id] = realtimeSinceStartup + 15f; LightMyFirePlugin.LogOreDiagnostic(DescribeStation(smelter) + " queue " + queued + "/" + smelter.m_maxOre + (awaiting ? "; waiting for a chest answer" : string.Empty) + ((cooldownLeft > 0f) ? ("; retry in " + cooldownLeft.ToString("0") + " s") : string.Empty) + ((queued > 2) ? ("; refills at " + 2 + " or fewer") : string.Empty) + "."); } } internal static void ScanAndRequestOre() { PruneStaleOutbound(); if (LightMyFireOreChest.HasActiveChests()) { Smelter[] array = Object.FindObjectsByType<Smelter>((FindObjectsInactive)0, (FindObjectsSortMode)0); int num = 0; while (array != null && num < array.Length) { OnSmelterUpdate(array[num]); num++; } } } private static void StartRequest(Smelter smelter, ZDOID smelterId, int missing) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: 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) float oreFeedRange = LightMyFirePlugin.GetOreFeedRange(); float rangeSqr = oreFeedRange * oreFeedRange; Vector3 position = ((Component)smelter).transform.position; LightMyFireOreChest.GetActiveChests(ChestBuffer); List<LightMyFireOreChest> list = null; List<float> list2 = null; for (int i = 0; i < ChestBuffer.Count; i++) { LightMyFireOreChest lightMyFireOreChest = ChestBuffer[i]; if (lightMyFireOreChest.IsReadyWithinRange(position, rangeSqr)) { if (list == null) { list = new List<LightMyFireOreChest>(); list2 = new List<float>(); } Vector3 val = ((Component)lightMyFireOreChest).transform.position - position; float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude; int j; for (j = 0; j < list2.Count && list2[j] <= sqrMagnitude; j++) { } list.Insert(j, lightMyFireOreChest); list2.Insert(j, sqrMagnitude); } } if (list == null) { NextAttempt[smelterId] = Time.realtimeSinceStartup + 5f; LightMyFirePlugin.LogOreDiagnostic("No Ore Chest within " + oreFeedRange.ToString("0.#") + " m of " + DescribeStation(smelter) + "."); return; } OutboundState outboundState = new OutboundState { SmelterId = smelterId, RemainingAmount = missing, AcceptedPrefabNames = GetAcceptedPrefabNames(smelter), Candidates = list, NextCandidateIndex = 0 }; LightMyFirePlugin.LogOreDiagnostic(DescribeStation(smelter) + " needs " + missing + " ore; asking " + list.Count + " Ore Chest(s) for: " + outboundState.AcceptedPrefabNames + "."); if (!TrySendNextRequest(outboundState)) { FinishRound(outboundState); } } internal static void PruneStaleOutbound() { if (PendingOutbound.Count == 0) { return; } float realtimeSinceStartup = Time.realtimeSinceStartup; List<long> list = null; foreach (KeyValuePair<long, OutboundState> item in PendingOutbound) { if (realtimeSinceStartup - item.Value.SentAtRealtime >= 20f) { if (list == null) { list = new List<long>(); } list.Add(item.Key); } } if (list == null) { return; } for (int i = 0; i < list.Count; i++) { if (PendingOutbound.TryGetValue(list[i], out var value)) { PendingOutbound.Remove(list[i]); LightMyFirePlugin.LogOreDiagnostic("Ore Chest did not answer within " + 20f + " s; trying the next chest."); value.NextCandidateIndex++; if (!TrySendNextRequest(value)) { FinishRound(value); } } } } private static void FinishRound(OutboundState state) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) SmeltersAwaitingResponse.Remove(state.SmelterId); if (state.AppliedAmount > 0) { NextAttempt.Remove(state.SmelterId); } else { NextAttempt[state.SmelterId] = Time.realtimeSinceStartup + 5f; } } private static string GetAcceptedPrefabNames(Smelter smelter) { List<string> list = new List<string>(); if (smelter.m_conversion != null) { for (int i = 0; i < smelter.m_conversion.Count; i++) { ItemConversion val = smelter.m_conversion[i]; if (val != null && (Object)(object)val.m_from != (Object)null && !list.Contains(((Object)((Component)val.m_from).gameObject).name)) { list.Add(((Object)((Component)val.m_from).gameObject).name); } } } return string.Join(",", list.ToArray()); } private static bool TrySendNextRequest(OutboundState state) { //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) if (state.Candidates == null || state.RemainingAmount <= 0) { return false; } while (state.NextCandidateIndex < state.Candidates.Count) { LightMyFireOreChest lightMyFireOreChest = state.Candidates[state.NextCandidateIndex]; if ((Object)(object)lightMyFireOreChest == (Object)null) { state.NextCandidateIndex++; continue; } int requestedAmount = Mathf.Min(state.RemainingAmount, 50); long num = NextTransactionId(); state.CurrentChest = lightMyFireOreChest; state.SentAtRealtime = Time.realtimeSinceStartup; PendingOutbound[num] = state; SmeltersAwaitingResponse.Add(state.SmelterId); if (!lightMyFireOreChest.SendRequestOre(num, state.SmelterId, requestedAmount, state.AcceptedPrefabNames)) { PendingOutbound.Remove(num); SmeltersAwaitingResponse.Remove(state.SmelterId); state.NextCandidateIndex++; continue; } return true; } return false; } internal static void SendGrant(long transactionId, ZDOID chestId, ZDOID smelterId, string itemPrefabName, int amount, bool cheated) { //IL_0014: 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_005c: Unknown result type (might be due to invalid IL or missing references) if (ZRoutedRpc.instance != null && ZDOMan.instance != null) { ZDO zDO = ZDOMan.instance.GetZDO(smelterId); long num = ((zDO == null) ? 0 : zDO.GetOwner()); if (num == 0L) { LightMyFirePlugin.LogOreDiagnostic("Ore grant not sent: the smelter has no owner right now."); return; } ZRoutedRpc.instance.InvokeRoutedRPC(num, "R4V9N1_LightMyFire_GrantOre", new object[6] { transactionId, chestId, smelterId, itemPrefabName ?? string.Empty, amount, cheated }); } } internal static void RPC_GrantOre(long sender, long transactionId, ZDOID chestId, ZDOID smelterId, string itemPrefabName, int grantedAmount, bool cheated) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) OutboundState value; bool num = PendingOutbound.TryGetValue(transactionId, out value); LightMyFireOreChest lightMyFireOreChest = (num ? value.CurrentChest : LightMyFireOreChest.FindByZdoId(chestId)); if (!num) { LightMyFirePlugin.LogOreDiagnostic("Late or unknown ore grant (" + grantedAmount + " " + itemPrefabName + "); returned to the chest."); if (grantedAmount > 0 && (Object)(object)lightMyFireOreChest != (Object)null) { lightMyFireOreChest.SendRefundOre(transactionId, grantedAmount); } return; } PendingOutbound.Remove(transactionId); if (grantedAmount <= 0) { LightMyFirePlugin.LogOreDiagnostic("Ore Chest had no ore this station takes."); value.NextCandidateIndex++; if (!TrySendNextRequest(value)) { FinishRound(value); } return; } int num2 = TryQueueOre(smelterId, itemPrefabName, grantedAmount, cheated); int num3 = grantedAmount - num2; if ((Object)(object)lightMyFireOreChest != (Object)null) { if (num3 > 0) { lightMyFireOreChest.SendRefundOre(transactionId, num3); } else { lightMyFireOreChest.SendAckOre(transactionId); } } value.AppliedAmount += num2; value.RemainingAmount = Math.Max(0, value.RemainingAmount - num2); if (num2 <= 0 || num3 > 0 || value.RemainingAmount <= 0 || !TrySendNextRequest(value)) { FinishRound(value); } } private static int TryQueueOre(ZDOID smelterId, string itemPrefabName, int grantedAmount, bool cheated) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)ZNetScene.instance == (Object)null || string.IsNullOrEmpty(itemPrefabName) || QueueOreMethod == null || IsItemAllowedMethod == null) { return 0; } GameObject val = ZNetScene.instance.FindInstance(smelterId); Smelter val2 = (((Object)(object)val == (Object)null) ? null : val.GetComponent<Smelter>()); if ((Object)(object)val != (Object)null && (Object)(object)val2 == (Object)null) { val2 = val.GetComponentInChildren<Smelter>(true); } ZNetView val3 = (((Object)(object)val2 == (Object)null) ? null : SmelterView.Invoke(val2)); ZDO val4 = (((Object)(object)val3 == (Object)null || !val3.IsValid() || !val3.IsOwner()) ? null : val3.GetZDO()); if (val4 == null) { LightMyFirePlugin.LogOreDiagnostic("Granted " + grantedAmount + " " + itemPrefabName + " returned: the smelter is no longer loaded or owned here."); return 0; } if (!(bool)IsItemAllowedMethod.Invoke(val2, new object[1] { itemPrefabName })) { LightMyFirePlugin.LogOreDiagnostic("Granted " + itemPrefabName + " returned: " + DescribeStation(val2) + " does not take it."); return 0; } int num = Mathf.Clamp(val2.m_maxOre - val4.GetInt(ZDOVars.s_queued, 0), 0, 50); int num2 = Mathf.Min(grantedAmount, num); object[] parameters = new object[2] { itemPrefabName, cheated }; for (int i = 0; i < num2; i++) { QueueOreMethod.Invoke(val2, parameters); } if (num2 > 0) { LightMyFirePlugin.LogOreTransfer(num2, itemPrefabName, DescribeStation(val2)); } return num2; } private static string DescribeStation(Smelter smelter) { if (Localization.instance == null) { return smelter.m_name; } return Localization.instance.Localize(smelter.m_name); } } [HarmonyPatch] internal static class SmelterOreFeedPatch { private static MethodBase TargetMethod() { return AccessTools.Method(typeof(Smelter), "UpdateSmelter", Type.EmptyTypes, (Type[])null); } private static void Postfix(Smelter __instance) { LightMyFireOreFeeder.OnSmelterUpdate(__instance); LightMyFireFeeder.OnSmelterUpdate(__instance); } } public sealed class LightMyFireOreLabel : MonoBehaviour { internal const string LabelName = "R4V9N1_LightMyFire_OreLabel"; internal const string Runes = "ᛟᚱᛖ"; private const float SurfaceGap = 0.003f; private void Start() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Invalid comparison between Unknown and I4 //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) if ((int)SystemInfo.graphicsDeviceType == 4) { ((Behaviour)this).enabled = false; return; } Transform val = ((Component)this).transform.Find("R4V9N1_LightMyFire_OreLabel"); if ((Object)(object)val == (Object)null) { return; } Vector3 forward = ((Component)this).transform.forward; Vector3 val2 = ((Component)this).transform.TransformPoint(new Vector3(val.localPosition.x, val.localPosition.y, val.localPosition.z - 1f)); Ray val3 = default(Ray); ((Ray)(ref val3))..ctor(val2, forward); float num = float.MaxValue; Collider[] componentsInChildren = ((Component)this).GetComponentsInChildren<Collider>(false); RaycastHit val4 = default(RaycastHit); for (int i = 0; i < componentsInChildren.Length; i++) { if ((Object)(object)componentsInChildren[i] != (Object)null && componentsInChildren[i].enabled && !componentsInChildren[i].isTrigger && componentsInChildren[i].Raycast(val3, ref val4, 2f) && ((RaycastHit)(ref val4)).distance < num) { num = ((RaycastHit)(ref val4)).distance; } } if (num < float.MaxValue) { val.position = val2 + forward * (num - 0.003f); } } internal static bool Attach(GameObject prefab, float centreHeight, float frontZ, float width) { //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) GameObject prefab2 = PrefabManager.Instance.GetPrefab("sign"); Sign val = (((Object)(object)prefab2 == (Object)null) ? null : prefab2.GetComponent<Sign>()); TextMeshProUGUI val2 = (((Object)(object)val == (Object)null) ? null : val.m_textWidget); Canvas val3 = (((Object)(object)val2 == (Object)null) ? null : ((Component)val2).GetComponentInParent<Canvas>(true)); if ((Object)(object)prefab == (Object)null || (Object)(object)val3 == (Object)null) { return false; } GameObject val4 = Object.Instantiate<GameObject>(((Component)val3).gameObject, prefab.transform, false); ((Object)val4).name = "R4V9N1_LightMyFire_OreLabel"; val4.transform.localPosition = new Vector3(0f, centreHeight, frontZ - 0.003f); val4.transform.localRotation = Quaternion.identity; val4.transform.localScale = Vector3.one; TextMeshProUGUI componentInChildren = val4.GetComponentInChildren<TextMeshProUGUI>(true); if ((Object)(object)componentInChildren == (Object)null) { Object.Destroy((Object)(object)val4); return false; } ((TMP_Text)componentInChildren).text = "ᛟᚱᛖ"; ((Graphic)componentInChildren).color = Color.black; ((TMP_Text)componentInChildren).enableAutoSizing = false; ((TMP_Text)componentInChildren).fontSize = 5f; ((TMP_Text)componentInChildren).alignment = (TextAlignmentOptions)514; ((TMP_Text)componentInChildren).textWrappingMode = (TextWrappingModes)0; ((Graphic)componentInChildren).raycastTarget = false; RectTransform rectTransform = ((TMP_Text)componentInChildren).rectTransform; float num = Mathf.Max(0.0001f, Mathf.Abs(((TMP_Text)componentInChildren).transform.localScale.x)); rectTransform.sizeDelta = new Vector2(width / num, 0.3f / num); ((TMP_Text)componentInChildren).transform.localPosition = Vector3.zero; if ((Object)(object)prefab.GetComponent<LightMyFireOreLabel>() == (Object)null) { prefab.AddComponent<LightMyFireOreLabel>(); } return true; } } internal static class LightMyFireAutoFuelToggle { internal const string AutoFuelOffKey = "R4V9N1_LightMyFire_AutoFuelOff"; internal static bool IsAutoFuelOff(ZDO zdo) { if (zdo != null) { return zdo.GetBool("R4V9N1_LightMyFire_AutoFuelOff", false); } return false; } internal static ZNetView GetView(CookingStation station) { if ((Object)(object)station == (Object)null) { return null; } ZNetView component = ((Component)station).GetComponent<ZNetView>(); if (!((Object)(object)component != (Object)null)) { return ((Component)station).GetComponentInParent<ZNetView>(); } return component; } } [HarmonyPatch(typeof(CookingStation), "Interact")] internal static class CookingStationAutoFuelInteractPatch { private static bool Prefix(CookingStation __instance, Humanoid user, bool hold, bool alt, ref bool __result) { if (!alt || hold || LightMyFirePlugin.GetSupportedFuelItemName(__instance) == null) { return true; } ZNetView view = LightMyFireAutoFuelToggle.GetView(__instance); if ((Object)(object)view == (Object)null || !view.IsValid() || view.GetZDO() == null) { return true; } if (!view.IsOwner()) { view.ClaimOwnership(); } bool flag = !LightMyFireAutoFuelToggle.IsAutoFuelOff(view.GetZDO()); view.GetZDO().Set("R4V9N1_LightMyFire_AutoFuelOff", flag); if ((Object)(object)user != (Object)null) { ((Character)user).Message((MessageType)2, flag ? "LightMyFire auto-fuel: Off" : "LightMyFire auto-fuel: On", 0, (Sprite)null, false); } __result = true; return false; } } [HarmonyPatch(typeof(CookingStation), "GetHoverText")] internal static class CookingStationAutoFuelHoverPatch { private static void Postfix(CookingStation __instance, ref string __result) { if (!string.IsNullOrEmpty(__result) && LightMyFirePlugin.GetSupportedFuelItemName(__instance) != null) { ZNetView view = LightMyFireAutoFuelToggle.GetView(__instance); if (!((Object)(object)view == (Object)null) && view.IsValid()) { bool flag = LightMyFireAutoFuelToggle.IsAutoFuelOff(view.GetZDO()); __result = __result + "\n[<color=yellow><b>$KEY_AltPlace + $KEY_Use</b></color>] LightMyFire auto-fuel: " + (flag ? "Off" : "On"); } } } } internal static class InventoryLinkWoodBarrelCompat { internal static void TryPatch(Harmony harmony, ManualLogSource log) { //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Expected O, but got Unknown Type type = AccessTools.TypeByName("InventoryLink.InventoryLinkPlugin"); if (type == null) { return; } MethodInfo methodInfo = AccessTools.Method(type, "IsReservedAutomationContainer", new Type[1] { typeof(Container) }, (Type[])null); if (methodInfo == null || methodInfo.ReturnType != typeof(bool)) { if (log != null) { log.LogWarning((object)"InventoryLink found, but its barrel-exclusion check changed; the Wood Barrel is not excluded from InventoryLink."); } return; } harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(InventoryLinkWoodBarrelCompat), "Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); if (log != null) { log.LogInfo((object)"InventoryLink found: the Wood Barrel and the Ore Chest are excluded from its material pulls."); } } private static void Postfix(Container container, ref bool __result) { if (!__result && !((Object)(object)container == (Object)null) && !((Object)(object)((Component)container).gameObject == (Object)null)) { string text = ((Object)((Component)container).gameObject).name ?? string.Empty; if (text.StartsWith("R4V9N1_LightMyFireWoodBarrel", StringComparison.Ordinal) || text.StartsWith("R4V9N1_LightMyFireOreChest", StringComparison.Ordinal)) { __result = true; } } } } [HarmonyPatch(typeof(Inventory), "StackAll")] internal static class FuelBarrelStackAllPatch { private static bool Prefix(Inventory __instance, Inventory fromInventory, bool message, ref int __result) { if (fromInventory == null || fromInventory == __instance || !LightMyFireItemFilter.TryGetExpectedFuel(__instance, out var fuelItemName)) { return true; } int num = CountAccepted(__instance, fuelItemName); List<ItemData> list = new List<ItemData>(fromInventory.GetAllItems()); for (int i = 0; i < list.Count; i++) { ItemData val = list[i]; if (val != null && val.m_shared != null && LightMyFireItemFilter.IsAcceptedFuelName(fuelItemName, val.m_shared.m_name) && (!((Object)(object)Player.m_localPlayer != (Object)null) || !((Humanoid)Player.m_localPlayer).IsItemEquiped(val)) && __instance.AddItem(val)) { fromInventory.RemoveItem(val); } } int num2 = CountAccepted(__instance, fuelItemName) - num; if (message && (Object)(object)Player.m_localPlayer != (Object)null) { ((Character)Player.m_localPlayer).Message((MessageType)2, (num2 > 0) ? ("$msg_stackall " + num2) : "$msg_stackall_none", 0, (Sprite)null, false); } __result = num2; return false; } private static int CountAccepted(Inventory inventory, string fuelItemName) { int num = 0; List<ItemData> allItems = inventory.GetAllItems(); for (int i = 0; i < allItems.Count; i++) { if (allItems[i] != null && allItems[i].m_shared != null && LightMyFireItemFilter.IsAcceptedFuelName(fuelItemName, allItems[i].m_shared.m_name)) { num += allItems[i].m_stack; } } return num; } } [BepInPlugin("r4v9n1.lightmyfire", "LightMyFire", "1.1.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] public sealed class LightMyFirePlugin : BaseUnityPlugin { public const string PluginGuid = "r4v9n1.lightmyfire"; public const string PluginName = "LightMyFire"; public const string PluginVersion = "1.1.0"; public const string CreatorCredit = "Created by R4V9N1"; internal const string CoalItemName = "$item_coal"; internal const string ResinItemName = "$item_resin"; internal const string WoodItemName = "$item_wood"; internal const string CoalBarrelPrefabName = "R4V9N1_LightMyFireCoalBarrel"; internal const string ResinBarrelPrefabName = "R4V9N1_LightMyFireResinBarrel"; internal const string WoodBarrelPrefabName = "R4V9N1_LightMyFireWoodBarrel"; internal const string OreChestPrefabName = "R4V9N1_LightMyFireOreChest"; internal const string OreChestFilterToken = "R4V9N1_LightMyFire_Ore"; private const string OreChestBasePrefabName = "piece_chest"; private const string CoalItemPrefabName = "Coal"; private const string ResinItemPrefabName = "Resin"; private const string WoodItemPrefabName = "Wood"; private static ConfigEntry<bool> _enabled;