Decompiled source of LightMyFire Coal Resin v0.5.0

plugins/LightMyFire/LightMyFire.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using UnityEngine;
using UnityEngine.Rendering;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("LightMyFire")]
[assembly: AssemblyFileVersion("0.5.0")]
[assembly: AssemblyCompany("R4V9N1")]
[assembly: AssemblyDescription("Created by R4V9N1")]
[assembly: AssemblyProduct("LightMyFire")]
[assembly: AssemblyCopyright("Created by R4V9N1")]
[assembly: AssemblyMetadata("Creator", "Created by R4V9N1")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("0.5.0.0")]
namespace LightMyFire;

public sealed class LightMyFireBarrel : MonoBehaviour
{
	private struct PendingReservation
	{
		public int Amount;

		public float ReservedAtRealtime;
	}

	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 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 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();
		}
	}

	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);
		}
		_runtimeInitialized = true;
		LightMyFirePlugin.LogBarrelRuntimeReady(((Object)((Component)this).gameObject).name, _fuelItemName, GetFuelCount());
		return true;
	}

	private void EnsureConfiguration()
	{
		if (string.IsNullOrEmpty(_fuelItemName))
		{
			bool flag = ((Object)((Component)this).gameObject).name.IndexOf("ResinBarrel", StringComparison.OrdinalIgnoreCase) >= 0;
			_fuelItemName = (flag ? "$item_resin" : "$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;
		_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;
		List<long> list = null;
		foreach (KeyValuePair<long, PendingReservation> pendingReservation in _pendingReservations)
		{
			if (realtimeSinceStartup - pendingReservation.Value.ReservedAtRealtime >= 30f)
			{
				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);
			}
		}
	}

	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)
	{
		if (amount > 0 && _inventory != null)
		{
			EnsureConfiguration();
			_inventory.AddItem(_fuelItemName, amount, 1, 0, 0L, string.Empty, false);
		}
	}

	private void RPC_RequestFuel(long sender, long transactionId, ZDOID fireplaceId, int requestedAmount)
	{
		//IL_00a3: 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)
		//IL_006b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0070: 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))
		{
			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,
				ReservedAtRealtime = Time.realtimeSinceStartup
			};
			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.Remove(transactionId);
		}
	}

	private void RPC_RefundFuel(long sender, long transactionId, int amount)
	{
		if (!((Object)(object)_nview == (Object)null) && _nview.IsValid() && _nview.IsOwner() && _pendingReservations.TryGetValue(transactionId, out var value))
		{
			_pendingReservations.Remove(transactionId);
			int amount2 = Mathf.Clamp(amount, 0, value.Amount);
			RefundLocally(amount2);
		}
	}

	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 void SendRequestFuel(long transactionId, ZDOID fireplaceId, int requestedAmount)
	{
		//IL_0044: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)_nview != (Object)null && _nview.IsValid() && _nview.HasOwner())
		{
			_nview.InvokeRPC("R4V9N1_LightMyFire_RequestFuel", new object[3]
			{
				transactionId,
				fireplaceId,
				Mathf.Clamp(requestedAmount, 0, 50)
			});
		}
	}

	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 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 Barrel;

		public ZDOID FireplaceId;

		public int RequestedAmount;

		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 HashSet<ZDOID> FireplacesAwaitingResponse = new HashSet<ZDOID>();

	private static long _txCounter;

	private static long NextTransactionId()
	{
		long uID = ZNet.GetUID();
		_txCounter++;
		return (uID << 20) ^ (_txCounter & 0xFFFFF);
	}

	internal static void PruneStaleOutbound()
	{
		//IL_00a7: 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]);
				FireplacesAwaitingResponse.Remove(value.FireplaceId);
			}
		}
	}

	internal static void ScanAndRequestRefills()
	{
		//IL_00aa: 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_00b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0121: Unknown result type (might be due to invalid IL or missing references)
		//IL_0126: Unknown result type (might be due to invalid IL or missing references)
		//IL_0141: Unknown result type (might be due to invalid IL or missing references)
		//IL_0157: Unknown result type (might be due to invalid IL or missing references)
		//IL_015c: Unknown result type (might be due to invalid IL or missing references)
		//IL_015e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0163: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
		//IL_0201: Unknown result type (might be due to invalid IL or missing references)
		//IL_0227: Unknown result type (might be due to invalid IL or missing references)
		//IL_0233: Unknown result type (might be due to invalid IL or missing references)
		PruneStaleOutbound();
		if (!LightMyFireBarrel.HasActiveBarrels())
		{
			return;
		}
		Fireplace[] array = Object.FindObjectsByType<Fireplace>((FindObjectsInactive)0, (FindObjectsSortMode)0);
		if (array == null || array.Length == 0)
		{
			LightMyFirePlugin.LogScanSummary(0, 0, 0, 0, 0, 0);
			return;
		}
		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> list = new List<LightMyFireBarrel>();
		List<BarrelDistance> list2 = new List<BarrelDistance>();
		foreach (Fireplace val in array)
		{
			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 (FireplacesAwaitingResponse.Contains(uid))
			{
				continue;
			}
			string supportedFuelItemName = LightMyFirePlugin.GetSupportedFuelItemName(val);
			if (supportedFuelItemName == null)
			{
				continue;
			}
			num2++;
			float num6 = zDO.GetFloat(ZDOVars.s_fuel, 0f);
			int num7 = Mathf.FloorToInt(val.m_maxFuel - num6 + 0.001f);
			if (num7 <= 0)
			{
				continue;
			}
			num3++;
			if (!LightMyFireBarrel.TryFindActiveMatchingBarrels(supportedFuelItemName, list))
			{
				continue;
			}
			Vector3 position = ((Component)val).transform.position;
			list2.Clear();
			for (int j = 0; j < list.Count; j++)
			{
				LightMyFireBarrel lightMyFireBarrel = list[j];
				if (lightMyFireBarrel.IsWithinRange(position, rangeSqr))
				{
					Vector3 val3 = ((Component)lightMyFireBarrel).transform.position - position;
					list2.Add(new BarrelDistance(lightMyFireBarrel, ((Vector3)(ref val3)).sqrMagnitude));
				}
			}
			if (list2.Count != 0)
			{
				num4++;
				list2.Sort(delegate(BarrelDistance left, BarrelDistance right)
				{
					float distanceSqr = left.DistanceSqr;
					return distanceSqr.CompareTo(right.DistanceSqr);
				});
				LightMyFireBarrel barrel = list2[0].Barrel;
				int num8 = Mathf.Min(num7, 50);
				if (num8 > 0)
				{
					long num9 = NextTransactionId();
					PendingOutbound[num9] = new OutboundState
					{
						Barrel = barrel,
						FireplaceId = uid,
						RequestedAmount = num8,
						SentAtRealtime = Time.realtimeSinceStartup
					};
					FireplacesAwaitingResponse.Add(uid);
					barrel.SendRequestFuel(num9, uid, num8);
					num5++;
				}
			}
		}
		LightMyFirePlugin.LogScanSummary(array.Length, num, num2, num3, num4, num5);
	}

	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_0039: Unknown result type (might be due to invalid IL or missing references)
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		LightMyFireBarrel lightMyFireBarrel = null;
		OutboundState value;
		bool flag = PendingOutbound.TryGetValue(transactionId, out value);
		if (flag)
		{
			PendingOutbound.Remove(transactionId);
			FireplacesAwaitingResponse.Remove(value.FireplaceId);
			lightMyFireBarrel = value.Barrel;
		}
		else
		{
			lightMyFireBarrel = LightMyFireBarrel.FindByZdoId(barrelId);
		}
		if (grantedAmount <= 0)
		{
			return;
		}
		if (!flag)
		{
			RefundToBarrel(lightMyFireBarrel, transactionId, grantedAmount);
			return;
		}
		int num = TryApplyFuelToFireplace(fireplaceId, grantedAmount);
		int num2 = grantedAmount - num;
		if (num2 > 0)
		{
			RefundToBarrel(lightMyFireBarrel, transactionId, num2);
		}
		else if ((Object)(object)lightMyFireBarrel != (Object)null)
		{
			lightMyFireBarrel.SendAckApplied(transactionId);
		}
	}

	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;
		}
		Fireplace val2 = val.GetComponent<Fireplace>();
		if ((Object)(object)val2 == (Object)null)
		{
			val2 = val.GetComponentInChildren<Fireplace>(true);
		}
		ZNetView val3 = ResolveNetworkView(val2);
		if ((Object)(object)val2 == (Object)null || (Object)(object)val3 == (Object)null || !val3.IsValid() || !val3.IsOwner())
		{
			return 0;
		}
		ZDO zDO = val3.GetZDO();
		if (zDO == null)
		{
			return 0;
		}
		float num = zDO.GetFloat(ZDOVars.s_fuel, 0f);
		int num2 = Mathf.Clamp(Mathf.FloorToInt(val2.m_maxFuel - num + 0.001f), 0, 50);
		int num3 = Mathf.Min(grantedAmount, num2);
		if (num3 <= 0)
		{
			return 0;
		}
		val2.AddFuel((float)num3);
		LightMyFirePlugin.LogTransfer(num3, LightMyFirePlugin.GetSupportedFuelItemName(val2), val2);
		return num3;
	}

	private static ZNetView ResolveNetworkView(Fireplace fireplace)
	{
		if ((Object)(object)fireplace == (Object)null)
		{
			return null;
		}
		ZNetView component = ((Component)fireplace).GetComponent<ZNetView>();
		if ((Object)(object)component != (Object)null)
		{
			return component;
		}
		component = ((Component)fireplace).GetComponentInParent<ZNetView>();
		if ((Object)(object)component != (Object)null)
		{
			return component;
		}
		return ((Component)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, "$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);
		}
		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);
	}

	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) + ")";
	}
}
[BepInPlugin("r4v9n1.lightmyfire", "LightMyFire", "0.5.0")]
[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 = "0.5.0";

	public const string CreatorCredit = "Created by R4V9N1";

	internal const string CoalItemName = "$item_coal";

	internal const string ResinItemName = "$item_resin";

	internal const string CoalBarrelPrefabName = "R4V9N1_LightMyFireCoalBarrel";

	internal const string ResinBarrelPrefabName = "R4V9N1_LightMyFireResinBarrel";

	private const string AssetBundleResourceName = "LightMyFire.Assets.lightmyfire_assets";

	private const string CoalVisualAssetPath = "Assets/LightMyFire/Generated/Prefabs/LightMyFire_CoalBarrelVisual.prefab";

	private const string ResinVisualAssetPath = "Assets/LightMyFire/Generated/Prefabs/LightMyFire_ResinBarrelVisual.prefab";

	private static ConfigEntry<bool> _enabled;

	private static ConfigEntry<float> _feedRange;

	private static ConfigEntry<float> _refillIntervalMinutes;

	private static ConfigEntry<bool> _logTransfers;

	private static ConfigEntry<bool> _logDiagnostics;

	private static ManualLogSource _log;

	private bool _piecesRegistered;

	private float _nextRefillScan;

	private float _nextMaintenanceTick;

	private ZRoutedRpc _registeredRoutedRpcInstance;

	private AssetBundle _assetBundle;

	private GameObject _coalVisualPrefab;

	private GameObject _resinVisualPrefab;

	private void Awake()
	{
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: Expected O, but got Unknown
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_0041: Expected O, but got Unknown
		//IL_0077: Unknown result type (might be due to invalid IL or missing references)
		//IL_007c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0084: Expected O, but got Unknown
		//IL_0084: Unknown result type (might be due to invalid IL or missing references)
		//IL_008e: Expected O, but got Unknown
		//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d1: Expected O, but got Unknown
		//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00db: Expected O, but got Unknown
		_log = ((BaseUnityPlugin)this).Logger;
		_enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, new ConfigDescription("Enable automatic coal and resin feeding. Server-controlled.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
		{
			IsAdminOnly = true
		} }));
		_feedRange = ((BaseUnityPlugin)this).Config.Bind<float>("Feeding", "Range", 50f, new ConfigDescription("Maximum distance in metres from a matching LightMyFire barrel to a compatible light source. Server-controlled.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 100f), new object[1] { (object)new ConfigurationManagerAttributes
		{
			IsAdminOnly = true
		} }));
		_refillIntervalMinutes = ((BaseUnityPlugin)this).Config.Bind<float>("Feeding", "RefillIntervalMinutes", 5f, new ConfigDescription("How often LightMyFire checks for compatible lights that need topping up, in minutes. Server-controlled.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 60f), new object[1] { (object)new ConfigurationManagerAttributes
		{
			IsAdminOnly = true
		} }));
		_logTransfers = ((BaseUnityPlugin)this).Config.Bind<bool>("Diagnostics", "LogTransfers", false, "Log successful automatic fuel transfers. Local/diagnostic only, not synced.");
		_logDiagnostics = ((BaseUnityPlugin)this).Config.Bind<bool>("Diagnostics", "LogDiagnostics", false, "Log barrel runtime initialization and refill-scan summaries. Useful when diagnosing a light that is not being fed.");
		if (Mathf.Approximately(_refillIntervalMinutes.Value, 15f))
		{
			_refillIntervalMinutes.Value = 5f;
			((BaseUnityPlugin)this).Config.Save();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Migrated Feeding > RefillIntervalMinutes from the old 15-minute default to 5 minutes.");
		}
		_nextRefillScan = Time.realtimeSinceStartup + 10f;
		_nextMaintenanceTick = Time.realtimeSinceStartup + 5f;
		LightMyFireHarmonyPatches.Apply(((BaseUnityPlugin)this).Logger);
		if (!LoadVisualAssets())
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"LightMyFire could not load its embedded barrel models; piece registration is disabled.");
			return;
		}
		PrefabManager.OnVanillaPrefabsAvailable += RegisterBarrels;
		((BaseUnityPlugin)this).Logger.LogInfo((object)"LightMyFire 0.5.0 loaded.");
		((BaseUnityPlugin)this).Logger.LogInfo((object)"A shared timed scan tops up under-fueled coal and resin lights from matching barrels.");
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Created by R4V9N1.");
	}

	private void OnDestroy()
	{
		PrefabManager.OnVanillaPrefabsAvailable -= RegisterBarrels;
		LightMyFireHarmonyPatches.Unpatch();
		if ((Object)(object)_assetBundle != (Object)null)
		{
			_assetBundle.Unload(false);
			_assetBundle = null;
		}
	}

	private bool LoadVisualAssets()
	{
		try
		{
			using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("LightMyFire.Assets.lightmyfire_assets"))
			{
				if (stream == null)
				{
					((BaseUnityPlugin)this).Logger.LogError((object)"Missing embedded resource 'LightMyFire.Assets.lightmyfire_assets'.");
					return false;
				}
				byte[] array = new byte[stream.Length];
				int i;
				int num;
				for (i = 0; i < array.Length; i += num)
				{
					num = stream.Read(array, i, array.Length - i);
					if (num <= 0)
					{
						break;
					}
				}
				if (i != array.Length)
				{
					((BaseUnityPlugin)this).Logger.LogError((object)"The embedded barrel AssetBundle could not be read completely.");
					return false;
				}
				_assetBundle = AssetBundle.LoadFromMemory(array);
			}
			if ((Object)(object)_assetBundle == (Object)null)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)"Unity could not load the embedded barrel AssetBundle.");
				return false;
			}
			_coalVisualPrefab = _assetBundle.LoadAsset<GameObject>("Assets/LightMyFire/Generated/Prefabs/LightMyFire_CoalBarrelVisual.prefab");
			_resinVisualPrefab = _assetBundle.LoadAsset<GameObject>("Assets/LightMyFire/Generated/Prefabs/LightMyFire_ResinBarrelVisual.prefab");
			if ((Object)(object)_coalVisualPrefab == (Object)null || (Object)(object)_resinVisualPrefab == (Object)null)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)"The embedded AssetBundle is missing one or both barrel visual prefabs.");
				return false;
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Loaded custom coal and resin barrel models from the embedded Unity AssetBundle.");
			return true;
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("Failed to load custom barrel models: " + ex));
			return false;
		}
	}

	private void Update()
	{
		if (ZRoutedRpc.instance != null && _registeredRoutedRpcInstance != ZRoutedRpc.instance)
		{
			ZRoutedRpc.instance.Register<long, ZDOID, ZDOID, int>("R4V9N1_LightMyFire_GrantFuel", (Method<long, ZDOID, ZDOID, int>)LightMyFireFeeder.RPC_GrantFuel);
			_registeredRoutedRpcInstance = ZRoutedRpc.instance;
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Registered LightMyFire cross-peer fuel grant RPC.");
		}
		if (!_piecesRegistered)
		{
			return;
		}
		float realtimeSinceStartup = Time.realtimeSinceStartup;
		if (realtimeSinceStartup >= _nextMaintenanceTick)
		{
			_nextMaintenanceTick = realtimeSinceStartup + 10f;
			LightMyFireBarrel.TickMaintenance();
			LightMyFireBarrel.EjectInvalidItemsFromOwnedBarrels();
		}
		if (!IsEnabled())
		{
			return;
		}
		if (!LightMyFireBarrel.HasActiveBarrels())
		{
			if (realtimeSinceStartup >= _nextRefillScan)
			{
				float num = ((_refillIntervalMinutes == null) ? 5f : Mathf.Clamp(_refillIntervalMinutes.Value, 0.5f, 60f));
				_nextRefillScan = realtimeSinceStartup + num * 60f;
				LogNoActiveBarrels();
			}
		}
		else if (!(realtimeSinceStartup < _nextRefillScan))
		{
			float num2 = ((_refillIntervalMinutes == null) ? 5f : Mathf.Clamp(_refillIntervalMinutes.Value, 0.5f, 60f));
			_nextRefillScan = realtimeSinceStartup + num2 * 60f;
			LightMyFireFeeder.ScanAndRequestRefills();
		}
	}

	private void RegisterBarrels()
	{
		if (_piecesRegistered)
		{
			return;
		}
		GameObject val = ResolveBaseBarrelPrefab();
		if ((Object)(object)val == (Object)null)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"Could not find any current Valheim build piece that behaves as a barrel/container. LightMyFire pieces were not registered.");
			return;
		}
		bool flag = RegisterBarrel("R4V9N1_LightMyFireCoalBarrel", "LightMyFire Coal Barrel", "Stores coal and refills empty coal-burning lights within range.", "$item_coal", _coalVisualPrefab, val);
		bool flag2 = RegisterBarrel("R4V9N1_LightMyFireResinBarrel", "LightMyFire Resin Barrel", "Stores resin and refills empty resin-burning lights within range.", "$item_resin", _resinVisualPrefab, val);
		_piecesRegistered = flag && flag2;
		if (_piecesRegistered)
		{
			PrefabManager.OnVanillaPrefabsAvailable -= RegisterBarrels;
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Registered the coal and resin barrels in Hammer > Misc with 32 inventory slots each.");
		}
	}

	private GameObject ResolveBaseBarrelPrefab()
	{
		string[] array = new string[5] { "piece_chestbarrel", "piece_chest_barrel", "piece_barrel", "piece_barrel_wood", "barrel" };
		for (int i = 0; i < array.Length; i++)
		{
			GameObject prefab = PrefabManager.Instance.GetPrefab(array[i]);
			if (IsUsableContainerPiece(prefab))
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Using Valheim barrel base prefab '" + ((Object)prefab).name + "'."));
				return prefab;
			}
		}
		GameObject val = null;
		int num = int.MinValue;
		foreach (KeyValuePair<string, Object> prefab3 in Cache.GetPrefabs(typeof(GameObject)))
		{
			Object value = prefab3.Value;
			GameObject val2 = (GameObject)(object)((value is GameObject) ? value : null);
			if (IsUsableContainerPiece(val2))
			{
				string text = (string.IsNullOrEmpty(((Object)val2).name) ? prefab3.Key : ((Object)val2).name).ToLowerInvariant();
				int num2 = 0;
				if (text.Contains("barrel"))
				{
					num2 += 1000;
				}
				if (text.StartsWith("piece_"))
				{
					num2 += 100;
				}
				if (text.Contains("wood"))
				{
					num2 += 30;
				}
				if (text.Contains("chest"))
				{
					num2 += 10;
				}
				if (text.Contains("blackmetal"))
				{
					num2 -= 20;
				}
				if (text.Contains("cart"))
				{
					num2 -= 500;
				}
				if (num2 > num)
				{
					val = val2;
					num = num2;
				}
			}
		}
		if ((Object)(object)val != (Object)null && num >= 1000)
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)("Discovered current Valheim barrel base prefab '" + ((Object)val).name + "' dynamically."));
			return val;
		}
		string[] array2 = new string[3] { "piece_chest", "piece_chest_wood", "piece_chest_private" };
		for (int j = 0; j < array2.Length; j++)
		{
			GameObject prefab2 = PrefabManager.Instance.GetPrefab(array2[j]);
			if (IsUsableContainerPiece(prefab2))
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("No barrel-named container prefab was found; using fallback container '" + ((Object)prefab2).name + "'."));
				return prefab2;
			}
		}
		if ((Object)(object)val != (Object)null)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)("No barrel-named container prefab was found; using discovered container '" + ((Object)val).name + "'."));
			return val;
		}
		return null;
	}

	private static bool IsUsableContainerPiece(GameObject prefab)
	{
		if ((Object)(object)prefab == (Object)null)
		{
			return false;
		}
		if ((Object)(object)prefab.GetComponent<Piece>() != (Object)null && (Object)(object)prefab.GetComponent<Container>() != (Object)null && (Object)(object)prefab.GetComponent<WearNTear>() != (Object)null && (Object)(object)prefab.GetComponent<ZNetView>() != (Object)null)
		{
			return prefab.GetComponentsInChildren<Collider>(true).Length != 0;
		}
		return false;
	}

	private bool RegisterBarrel(string prefabName, string displayName, string description, string fuelItemName, GameObject visualPrefab, GameObject baseBarrel)
	{
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		//IL_0044: Expected O, but got Unknown
		//IL_0077: Unknown result type (might be due to invalid IL or missing references)
		//IL_007d: Expected O, but got Unknown
		if (PieceManager.Instance.GetPiece(prefabName) != null)
		{
			return true;
		}
		PieceConfig val = new PieceConfig
		{
			Name = displayName,
			Description = description,
			PieceTable = "Hammer",
			Category = "Misc",
			CraftingStation = "Workbench"
		};
		val.AddRequirement("Wood", 100, true);
		val.AddRequirement("Iron", 40, true);
		val.AddRequirement("Tar", 40, true);
		CustomPiece val2 = new CustomPiece(prefabName, ((Object)baseBarrel).name, val);
		GameObject piecePrefab = val2.PiecePrefab;
		if ((Object)(object)piecePrefab == (Object)null)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("Jotunn could not clone custom piece '" + prefabName + "' from base '" + ((Object)baseBarrel).name + "'."));
			return false;
		}
		if (!ValidateNativeBarrelClone(piecePrefab, out var error))
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("Native barrel clone validation failed for '" + prefabName + "': " + error + ". Piece registration was cancelled."));
			Object.Destroy((Object)(object)piecePrefab);
			return false;
		}
		Container component = piecePrefab.GetComponent<Container>();
		component.m_name = displayName;
		component.m_width = 8;
		component.m_height = 4;
		component.m_autoDestroyEmpty = false;
		LightMyFireBarrel lightMyFireBarrel = piecePrefab.GetComponent<LightMyFireBarrel>();
		if ((Object)(object)lightMyFireBarrel == (Object)null)
		{
			lightMyFireBarrel = piecePrefab.AddComponent<LightMyFireBarrel>();
		}
		lightMyFireBarrel.Configure(fuelItemName);
		if (!AttachNativeRangeMarker(piecePrefab))
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not attach LightMyFire dotted feeding-radius ring to '" + displayName + "'. The barrel will still function, but its feeding-radius ring will be unavailable."));
		}
		if (!AttachBarrelDecoration(piecePrefab, visualPrefab))
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("Could not attach the barrel decoration for '" + displayName + "'; registration was cancelled."));
			Object.Destroy((Object)(object)piecePrefab);
			return false;
		}
		PieceManager.Instance.AddPiece(val2);
		((BaseUnityPlugin)this).Logger.LogInfo((object)("Prepared '" + displayName + "' as a Jotunn native clone of '" + ((Object)baseBarrel).name + "' with " + piecePrefab.GetComponentsInChildren<Collider>(true).Length + " native collider(s); custom lid/plaque are visual-only."));
		return true;
	}

	private static bool AttachNativeRangeMarker(GameObject prefab)
	{
		//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d1: Expected O, but got Unknown
		//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
		//IL_0209: Unknown result type (might be due to invalid IL or missing references)
		//IL_018b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0191: Expected O, but got Unknown
		//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bb: Expected O, but got Unknown
		//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_011e: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)prefab == (Object)null)
		{
			return false;
		}
		try
		{
			Material val = null;
			GameObject prefab2 = PrefabManager.Instance.GetPrefab("piece_workbench");
			if ((Object)(object)prefab2 != (Object)null)
			{
				CraftingStation component = prefab2.GetComponent<CraftingStation>();
				if ((Object)(object)component != (Object)null)
				{
					BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
					FieldInfo field = typeof(CraftingStation).GetField("m_areaMarker", bindingAttr);
					GameObject val2 = (GameObject)((field == null) ? null : /*isinst with value type is only supported in some contexts*/);
					if ((Object)(object)val2 != (Object)null)
					{
						Renderer componentInChildren = val2.GetComponentInChildren<Renderer>(true);
						if ((Object)(object)componentInChildren != (Object)null && (Object)(object)componentInChildren.sharedMaterial != (Object)null)
						{
							val = new Material(componentInChildren.sharedMaterial);
							((Object)val).name = "LightMyFire_DottedRangeMaterial";
							if (val.HasProperty("_Color"))
							{
								val.SetColor("_Color", new Color(1f, 1f, 1f, 0.92f));
							}
							if (val.HasProperty("_BaseColor"))
							{
								val.SetColor("_BaseColor", new Color(1f, 1f, 1f, 0.92f));
							}
							val.renderQueue = 3100;
							if (val.HasProperty("_ZWrite"))
							{
								val.SetInt("_ZWrite", 0);
							}
						}
					}
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				Shader val3 = Shader.Find("Sprites/Default");
				if ((Object)(object)val3 == (Object)null)
				{
					val3 = Shader.Find("Unlit/Transparent");
				}
				if ((Object)(object)val3 == (Object)null)
				{
					return false;
				}
				val = new Material(val3);
				((Object)val).name = "LightMyFire_DottedRangeMaterial";
				val.color = new Color(1f, 1f, 1f, 0.92f);
				val.renderQueue = 3100;
			}
			GameObject val4 = new GameObject("R4V9N1_LightMyFire_RangeMarker");
			val4.transform.SetParent(prefab.transform, false);
			val4.transform.localPosition = Vector3.zero;
			val4.transform.localRotation = Quaternion.identity;
			val4.transform.localScale = Vector3.one;
			val4.AddComponent<MeshFilter>();
			MeshRenderer obj = val4.AddComponent<MeshRenderer>();
			((Renderer)obj).sharedMaterial = val;
			((Renderer)obj).shadowCastingMode = (ShadowCastingMode)0;
			((Renderer)obj).receiveShadows = false;
			val4.SetActive(false);
			LightMyFireRangeMarker lightMyFireRangeMarker = prefab.GetComponent<LightMyFireRangeMarker>();
			if ((Object)(object)lightMyFireRangeMarker == (Object)null)
			{
				lightMyFireRangeMarker = prefab.AddComponent<LightMyFireRangeMarker>();
			}
			lightMyFireRangeMarker.Configure(val4);
			return true;
		}
		catch (Exception ex)
		{
			if (_log != null)
			{
				_log.LogWarning((object)("Failed to prepare dotted feeding-radius ring: " + ex.Message));
			}
			return false;
		}
	}

	private static bool AttachBarrelDecoration(GameObject prefab, GameObject visualPrefab)
	{
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		//IL_0098: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_0148: Unknown result type (might be due to invalid IL or missing references)
		//IL_014f: Unknown result type (might be due to invalid IL or missing references)
		//IL_015d: 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)
		//IL_0187: Unknown result type (might be due to invalid IL or missing references)
		//IL_0191: Unknown result type (might be due to invalid IL or missing references)
		//IL_019d: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
		//IL_0214: Unknown result type (might be due to invalid IL or missing references)
		//IL_0220: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)prefab == (Object)null || (Object)(object)visualPrefab == (Object)null)
		{
			return false;
		}
		if (!TryGetPhysicalLocalBounds(prefab.transform, out var bounds))
		{
			Renderer[] componentsInChildren = prefab.GetComponentsInChildren<Renderer>(false);
			if (componentsInChildren.Length == 0)
			{
				return false;
			}
			bounds = GetCombinedLocalBounds(prefab.transform, componentsInChildren);
		}
		float num = Mathf.Min(((Bounds)(ref bounds)).size.x, ((Bounds)(ref bounds)).size.z);
		if (num <= 0.05f || float.IsNaN(num) || float.IsInfinity(num))
		{
			return false;
		}
		GameObject val = Object.Instantiate<GameObject>(visualPrefab, prefab.transform, false);
		((Object)val).name = "LightMyFireDecoration";
		val.transform.localPosition = Vector3.zero;
		val.transform.localRotation = Quaternion.identity;
		val.transform.localScale = Vector3.one;
		if (val.GetComponentsInChildren<Renderer>(true).Length == 0)
		{
			Object.Destroy((Object)(object)val);
			return false;
		}
		Collider[] componentsInChildren2 = val.GetComponentsInChildren<Collider>(true);
		for (int i = 0; i < componentsInChildren2.Length; i++)
		{
			Object.Destroy((Object)(object)componentsInChildren2[i]);
		}
		Transform val2 = val.transform.Find("MetalLid");
		Transform val3 = val.transform.Find("FrontPlaque");
		if ((Object)(object)val2 == (Object)null || (Object)(object)val3 == (Object)null)
		{
			Object.Destroy((Object)(object)val);
			return false;
		}
		float num2 = num * 0.9f / 0.95f;
		val2.localScale = Vector3.one * num2;
		val2.localPosition = new Vector3(((Bounds)(ref bounds)).center.x, ((Bounds)(ref bounds)).max.y + Mathf.Max(0.006f, num * 0.008f), ((Bounds)(ref bounds)).center.z);
		val2.localRotation = Quaternion.identity;
		float num3 = num * 0.42f / 0.56f;
		val3.localScale = new Vector3(0f - num3, num3, num3);
		val3.localPosition = new Vector3(((Bounds)(ref bounds)).center.x, ((Bounds)(ref bounds)).center.y + ((Bounds)(ref bounds)).size.y * 0.06f, ((Bounds)(ref bounds)).min.z - Mathf.Max(0.008f, num * 0.012f));
		val3.localRotation = Quaternion.identity;
		return true;
	}

	private static bool ValidateNativeBarrelClone(GameObject prefab, out string error)
	{
		error = null;
		if ((Object)(object)prefab.GetComponent<Piece>() == (Object)null)
		{
			error = "missing Piece";
			return false;
		}
		if ((Object)(object)prefab.GetComponent<ZNetView>() == (Object)null)
		{
			error = "missing ZNetView";
			return false;
		}
		if ((Object)(object)prefab.GetComponent<Container>() == (Object)null)
		{
			error = "missing Container";
			return false;
		}
		if ((Object)(object)prefab.GetComponent<WearNTear>() == (Object)null)
		{
			error = "missing WearNTear";
			return false;
		}
		if (prefab.GetComponentsInChildren<Collider>(true).Length == 0)
		{
			error = "missing native collider hierarchy";
			return false;
		}
		return true;
	}

	private static bool TryGetPhysicalLocalBounds(Transform root, out Bounds bounds)
	{
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0056: Unknown result type (might be due to invalid IL or missing references)
		//IL_005b: Unknown result type (might be due to invalid IL or missing references)
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0064: 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_0075: Unknown result type (might be due to invalid IL or missing references)
		Collider[] componentsInChildren = ((Component)root).GetComponentsInChildren<Collider>(true);
		bool initialized = false;
		bounds = new Bounds(Vector3.zero, Vector3.zero);
		foreach (Collider val in componentsInChildren)
		{
			if ((Object)(object)val == (Object)null || val.isTrigger)
			{
				continue;
			}
			if (TryGetColliderLocalBounds(val, out var bounds2))
			{
				EncapsulateLocalBounds(root, ((Component)val).transform, bounds2, ref bounds, ref initialized);
				continue;
			}
			Bounds bounds3 = val.bounds;
			Vector3 size = ((Bounds)(ref bounds3)).size;
			if (((Vector3)(ref size)).sqrMagnitude > 1E-06f)
			{
				EncapsulateWorldBounds(root, bounds3, ref bounds, ref initialized);
			}
		}
		return initialized;
	}

	private static bool TryGetColliderLocalBounds(Collider collider, out Bounds bounds)
	{
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_005e: 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_006a: 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_0074: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a1: 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)
		//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_0157: Unknown result type (might be due to invalid IL or missing references)
		//IL_015c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0161: Unknown result type (might be due to invalid IL or missing references)
		//IL_0166: Unknown result type (might be due to invalid IL or missing references)
		//IL_0135: Unknown result type (might be due to invalid IL or missing references)
		//IL_013a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0140: Unknown result type (might be due to invalid IL or missing references)
		//IL_0145: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f7: 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)
		BoxCollider val = (BoxCollider)(object)((collider is BoxCollider) ? collider : null);
		Vector3 size;
		if ((Object)(object)val != (Object)null)
		{
			bounds = new Bounds(val.center, val.size);
			size = val.size;
			return ((Vector3)(ref size)).sqrMagnitude > 1E-06f;
		}
		SphereCollider val2 = (SphereCollider)(object)((collider is SphereCollider) ? collider : null);
		if ((Object)(object)val2 != (Object)null)
		{
			float num = val2.radius * 2f;
			bounds = new Bounds(val2.center, Vector3.one * num);
			return num > 0.0001f;
		}
		CapsuleCollider val3 = (CapsuleCollider)(object)((collider is CapsuleCollider) ? collider : null);
		if ((Object)(object)val3 != (Object)null)
		{
			float num2 = val3.radius * 2f;
			Vector3 val4 = Vector3.one * num2;
			float num3 = Mathf.Max(val3.height, num2);
			if (val3.direction == 0)
			{
				val4.x = num3;
			}
			else if (val3.direction == 1)
			{
				val4.y = num3;
			}
			else
			{
				val4.z = num3;
			}
			bounds = new Bounds(val3.center, val4);
			return ((Vector3)(ref val4)).sqrMagnitude > 1E-06f;
		}
		MeshCollider val5 = (MeshCollider)(object)((collider is MeshCollider) ? collider : null);
		if ((Object)(object)val5 != (Object)null && (Object)(object)val5.sharedMesh != (Object)null)
		{
			bounds = val5.sharedMesh.bounds;
			size = ((Bounds)(ref bounds)).size;
			return ((Vector3)(ref size)).sqrMagnitude > 1E-06f;
		}
		bounds = new Bounds(Vector3.zero, Vector3.zero);
		return false;
	}

	private static void EncapsulateLocalBounds(Transform root, Transform source, Bounds localBounds, ref Bounds result, ref bool initialized)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_000a: Unknown result type (might be due to invalid IL or missing references)
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_0028: 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_0039: 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_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		//IL_0062: Unknown result type (might be due to invalid IL or missing references)
		//IL_0067: Unknown result type (might be due to invalid IL or missing references)
		//IL_006c: Unknown result type (might be due to invalid IL or missing references)
		//IL_008c: 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_0076: Unknown result type (might be due to invalid IL or missing references)
		//IL_007b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0080: Unknown result type (might be due to invalid IL or missing references)
		Vector3 min = ((Bounds)(ref localBounds)).min;
		Vector3 max = ((Bounds)(ref localBounds)).max;
		Vector3 val = default(Vector3);
		for (int i = 0; i < 2; i++)
		{
			for (int j = 0; j < 2; j++)
			{
				for (int k = 0; k < 2; k++)
				{
					((Vector3)(ref val))..ctor((i == 0) ? min.x : max.x, (j == 0) ? min.y : max.y, (k == 0) ? min.z : max.z);
					Vector3 val2 = root.InverseTransformPoint(source.TransformPoint(val));
					if (!initialized)
					{
						result = new Bounds(val2, Vector3.zero);
						initialized = true;
					}
					else
					{
						((Bounds)(ref result)).Encapsulate(val2);
					}
				}
			}
		}
	}

	private static void EncapsulateWorldBounds(Transform root, Bounds world, ref Bounds result, ref bool initialized)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_000a: Unknown result type (might be due to invalid IL or missing references)
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0025: 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_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		//IL_0048: Unknown result type (might be due to invalid IL or missing references)
		//IL_005c: Unknown result type (might be due to invalid IL or missing references)
		//IL_005e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0063: Unknown result type (might be due to invalid IL or missing references)
		//IL_0081: Unknown result type (might be due to invalid IL or missing references)
		//IL_006a: Unknown result type (might be due to invalid IL or missing references)
		//IL_006c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0071: Unknown result type (might be due to invalid IL or missing references)
		//IL_0076: Unknown result type (might be due to invalid IL or missing references)
		Vector3 min = ((Bounds)(ref world)).min;
		Vector3 max = ((Bounds)(ref world)).max;
		Vector3 val = default(Vector3);
		for (int i = 0; i < 2; i++)
		{
			for (int j = 0; j < 2; j++)
			{
				for (int k = 0; k < 2; k++)
				{
					((Vector3)(ref val))..ctor((i == 0) ? min.x : max.x, (j == 0) ? min.y : max.y, (k == 0) ? min.z : max.z);
					Vector3 val2 = root.InverseTransformPoint(val);
					if (!initialized)
					{
						result = new Bounds(val2, Vector3.zero);
						initialized = true;
					}
					else
					{
						((Bounds)(ref result)).Encapsulate(val2);
					}
				}
			}
		}
	}

	private static Bounds GetCombinedLocalBounds(Transform root, Renderer[] renderers)
	{
		//IL_0004: Unknown result type (might be due to invalid IL or missing references)
		//IL_0009: 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_0026: Unknown result type (might be due to invalid IL or missing references)
		bool initialized = false;
		Bounds result = default(Bounds);
		((Bounds)(ref result))..ctor(Vector3.zero, Vector3.zero);
		for (int i = 0; i < renderers.Length; i++)
		{
			if (!((Object)(object)renderers[i] == (Object)null))
			{
				EncapsulateWorldBounds(root, renderers[i].bounds, ref result, ref initialized);
			}
		}
		return result;
	}

	internal static bool IsDiagnosticsEnabled()
	{
		if (_logDiagnostics != null)
		{
			return _logDiagnostics.Value;
		}
		return false;
	}

	internal static void LogNoActiveBarrels()
	{
		if (IsDiagnosticsEnabled() && _log != null)
		{
			_log.LogWarning((object)"Refill scan skipped: no runtime-ready LightMyFire barrels are registered on this peer.");
		}
	}

	internal static void LogBarrelRuntimeReady(string objectName, string fuelItemName, int fuelCount)
	{
		if (IsDiagnosticsEnabled() && _log != null)
		{
			string text = (string.Equals(fuelItemName, "$item_resin", StringComparison.Ordinal) ? "resin" : "coal");
			_log.LogInfo((object)("Runtime-ready " + text + " barrel '" + objectName + "' with " + fuelCount + " fuel item(s)."));
		}
	}

	internal static void LogScanSummary(int fireplacesFound, int ownedFireplaces, int compatibleFireplaces, int underFueledFireplaces, int inRangeMatches, int requestsSent)
	{
		if (IsDiagnosticsEnabled() && _log != null)
		{
			_log.LogInfo((object)("Refill scan: fireplaces=" + fireplacesFound + ", owned=" + ownedFireplaces + ", compatible=" + compatibleFireplaces + ", needFuel=" + underFueledFireplaces + ", inRange=" + inRangeMatches + ", requests=" + requestsSent + "."));
		}
	}

	internal static bool IsEnabled()
	{
		if (_enabled != null)
		{
			return _enabled.Value;
		}
		return false;
	}

	internal static float GetFeedRange()
	{
		if (_feedRange != null)
		{
			return Mathf.Clamp(_feedRange.Value, 1f, 100f);
		}
		return 50f;
	}

	internal static void LogTransfer(int amount, string fuelItemName, Fireplace fireplace)
	{
		if (_logTransfers != null && _logTransfers.Value && _log != null && !((Object)(object)fireplace == (Object)null) && amount > 0)
		{
			string text = ((fuelItemName == "$item_resin") ? "resin" : "coal");
			_log.LogInfo((object)("Topped up " + fireplace.GetHoverName() + " with " + amount + " " + text + "."));
		}
	}

	internal static void LogInvalidItemEjection(int count, string barrelObjectName)
	{
		if (_log != null && count > 0)
		{
			_log.LogWarning((object)("Ejected " + count + " item stack(s) that did not match the configured fuel type from '" + barrelObjectName + "'."));
		}
	}

	internal static void LogRejectedInsertion(string expectedFuelName, string rejectedItemName, string entryPoint)
	{
		if (IsDiagnosticsEnabled() && _log != null)
		{
			string text = (string.Equals(expectedFuelName, "$item_resin", StringComparison.Ordinal) ? "Resin" : "Coal");
			string text2 = (string.IsNullOrEmpty(rejectedItemName) ? "unknown item" : rejectedItemName);
			_log.LogInfo((object)("Rejected '" + text2 + "' from " + text + " barrel via " + entryPoint + "."));
		}
	}

	internal static string GetSupportedFuelItemName(Fireplace fireplace)
	{
		if ((Object)(object)fireplace == (Object)null || fireplace.m_infiniteFuel || fireplace.m_maxFuel <= 0f || (Object)(object)fireplace.m_fuelItem == (Object)null || fireplace.m_fuelItem.m_itemData == null || fireplace.m_fuelItem.m_itemData.m_shared == null)
		{
			return null;
		}
		string name = fireplace.m_fuelItem.m_itemData.m_shared.m_name;
		if (!string.Equals(name, "$item_coal", StringComparison.Ordinal) && !string.Equals(name, "$item_resin", StringComparison.Ordinal))
		{
			return null;
		}
		return name;
	}

	internal static bool IsCompatibleFuelLight(Fireplace fireplace, string fuelItemName)
	{
		string supportedFuelItemName = GetSupportedFuelItemName(fireplace);
		if (supportedFuelItemName != null)
		{
			return string.Equals(supportedFuelItemName, fuelItemName, StringComparison.Ordinal);
		}
		return false;
	}
}
public sealed class LightMyFireRangeMarker : MonoBehaviour
{
	private const string MarkerName = "R4V9N1_LightMyFire_RangeMarker";

	private const float DotSpacingMetres = 1.25f;

	private const float DotLengthMetres = 0.34f;

	private const float DotWidthMetres = 0.14f;

	private const float HeightOffset = 0.055f;

	private const int MinDotCount = 32;

	private const int MaxDotCount = 512;

	private static readonly BindingFlags Flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;

	private static readonly FieldInfo PlacementGhostField = typeof(Player).GetField("m_placementGhost", Flags);

	private static readonly FieldInfo CurrentContainerField = typeof(InventoryGui).GetField("m_currentContainer", Flags);

	private static readonly MethodInfo ContainerIsInUseMethod = typeof(Container).GetMethod("IsInUse", Flags, null, Type.EmptyTypes, null);

	[SerializeField]
	private GameObject _marker;

	private MeshFilter _meshFilter;

	private Container _container;

	private ZNetView _nview;

	private Vector3 _lastMarkerWorldCenter = new Vector3(float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity);

	private float _lastAppliedRange = -1f;

	private bool _lastVisible;

	internal void Configure(GameObject marker)
	{
		_marker = marker;
		CacheMarkerParts();
		if ((Object)(object)_marker != (Object)null)
		{
			_marker.SetActive(false);
		}
	}

	private void Awake()
	{
		_container = ((Component)this).GetComponent<Container>();
		_nview = ((Component)this).GetComponent<ZNetView>();
		RecoverMarkerReference();
		if ((Object)(object)_marker != (Object)null)
		{
			_marker.SetActive(false);
		}
	}

	private void Start()
	{
		RecoverMarkerReference();
		ApplyCurrentRange(force: true, visible: true);
	}

	private void Update()
	{
		RecoverMarkerReference();
		if (!((Object)(object)_marker == (Object)null))
		{
			bool flag = IsPlacementPreviewInstance() || IsThisPlacementGhost() || IsThisInventoryOpenLocally();
			ApplyCurrentRange(force: false, flag);
			if (flag != _lastVisible || _marker.activeSelf != flag)
			{
				_marker.SetActive(flag);
				_lastVisible = flag;
			}
		}
	}

	private void RecoverMarkerReference()
	{
		if ((Object)(object)_marker == (Object)null)
		{
			Transform val = ((Component)this).transform.Find("R4V9N1_LightMyFire_RangeMarker");
			if ((Object)(object)val == (Object)null)
			{
				Transform[] componentsInChildren = ((Component)this).GetComponentsInChildren<Transform>(true);
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					if (string.Equals(((Object)componentsInChildren[i]).name, "R4V9N1_LightMyFire_RangeMarker", StringComparison.Ordinal))
					{
						val = componentsInChildren[i];
						break;
					}
				}
			}
			if ((Object)(object)val != (Object)null)
			{
				_marker = ((Component)val).gameObject;
			}
		}
		CacheMarkerParts();
	}

	private void CacheMarkerParts()
	{
		if ((Object)(object)_marker != (Object)null && (Object)(object)_meshFilter == (Object)null)
		{
			_meshFilter = _marker.GetComponent<MeshFilter>();
		}
	}

	private void ApplyCurrentRange(bool force, bool visible)
	{
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: 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)
		//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)_marker == (Object)null || (Object)(object)_meshFilter == (Object)null)
		{
			return;
		}
		float num = Mathf.Max(0.1f, LightMyFirePlugin.GetFeedRange());
		Vector3 position = ((Component)this).transform.position;
		Vector3 val = position - _lastMarkerWorldCenter;
		bool flag = ((Vector3)(ref val)).sqrMagnitude > 0.25f;
		if (force || !(Mathf.Abs(num - _lastAppliedRange) < 0.01f) || (visible && flag))
		{
			Mesh sharedMesh = _meshFilter.sharedMesh;
			_meshFilter.sharedMesh = BuildDottedRing(num);
			if ((Object)(object)sharedMesh != (Object)null && ((Object)sharedMesh).name.StartsWith("LightMyFire_DottedRange_", StringComparison.Ordinal))
			{
				Object.Destroy((Object)(object)sharedMesh);
			}
			_lastAppliedRange = num;
			_lastMarkerWorldCenter = position;
		}
	}

	private Mesh BuildDottedRing(float radius)
	{
		//IL_008f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0091: Unknown result type (might be due to invalid IL or missing references)
		//IL_009d: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_02bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_02df: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f5: Unknown result type (might be due to invalid IL or missing references)
		//IL_02fc: Expected O, but got Unknown
		//IL_0130: Unknown result type (might be due to invalid IL or missing references)
		//IL_0132: 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_013b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0140: Unknown result type (might be due to invalid IL or missing references)
		//IL_0144: Unknown result type (might be due to invalid IL or missing references)
		//IL_0149: Unknown result type (might be due to invalid IL or missing references)
		//IL_014e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0158: Unknown result type (might be due to invalid IL or missing references)
		//IL_015a: Unknown result type (might be due to invalid IL or missing references)
		//IL_015e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0163: Unknown result type (might be due to invalid IL or missing references)
		//IL_0168: Unknown result type (might be due to invalid IL or missing references)
		//IL_016c: 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_0180: Unknown result type (might be due to invalid IL or missing references)
		//IL_0182: Unknown result type (might be due to invalid IL or missing references)
		//IL_0186: Unknown result type (might be due to invalid IL or missing references)
		//IL_018b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0190: Unknown result type (might be due to invalid IL or missing references)
		//IL_0194: Unknown result type (might be due to invalid IL or missing references)
		//IL_0199: Unknown result type (might be due to invalid IL or missing references)
		//IL_019e: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0200: Unknown result type (might be due to invalid IL or missing references)
		//IL_0212: Unknown result type (might be due to invalid IL or missing references)
		//IL_0217: Unknown result type (might be due to invalid IL or missing references)
		//IL_022b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0230: Unknown result type (might be due to invalid IL or missing references)
		//IL_0244: Unknown result type (might be due to invalid IL or missing references)
		//IL_0249: Unknown result type (might be due to invalid IL or missing references)
		//IL_025d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0262: 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_00d5: 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_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)
		int num = Mathf.Clamp(Mathf.RoundToInt((float)Math.PI * 2f * radius / 1.25f), 32, 512);
		Vector3[] array = (Vector3[])(object)new Vector3[num * 4];
		Vector3[] array2 = (Vector3[])(object)new Vector3[array.Length];
		Vector2[] array3 = (Vector2[])(object)new Vector2[array.Length];
		int[] array4 = new int[num * 6];
		float num2 = 0.17f;
		float num3 = 0.07f;
		Vector3 val = default(Vector3);
		RaycastHit val3 = default(RaycastHit);
		Vector3 val4 = default(Vector3);
		Vector3 val5 = default(Vector3);
		Vector3 val6 = default(Vector3);
		for (int i = 0; i < num; i++)
		{
			float num4 = (float)Math.PI * 2f * (float)i / (float)num;
			float num5 = Mathf.Cos(num4);
			float num6 = Mathf.Sin(num4);
			((Vector3)(ref val))..ctor(num5 * radius, 0f, num6 * radius);
			Vector3 val2 = ((Component)this).transform.TransformPoint(val);
			float num7 = 0.055f;
			if (Physics.Raycast(val2 + Vector3.up * 120f, Vector3.down, ref val3, 240f, -1, (QueryTriggerInteraction)1))
			{
				num7 = ((Component)this).transform.InverseTransformPoint(((RaycastHit)(ref val3)).point + ((RaycastHit)(ref val3)).normal * 0.055f).y;
			}
			((Vector3)(ref val4))..ctor(num5 * radius, num7, num6 * radius);
			((Vector3)(ref val5))..ctor(0f - num6, 0f, num5);
			((Vector3)(ref val6))..ctor(num5, 0f, num6);
			int num8 = i * 4;
			array[num8] = val4 - val5 * num2 - val6 * num3;
			array[num8 + 1] = val4 + val5 * num2 - val6 * num3;
			array[num8 + 2] = val4 + val5 * num2 + val6 * num3;
			array[num8 + 3] = val4 - val5 * num2 + val6 * num3;
			array2[num8] = Vector3.up;
			array2[num8 + 1] = Vector3.up;
			array2[num8 + 2] = Vector3.up;
			array2[num8 + 3] = Vector3.up;
			array3[num8] = new Vector2(0f, 0f);
			array3[num8 + 1] = new Vector2(1f, 0f);
			array3[num8 + 2] = new Vector2(1f, 1f);
			array3[num8 + 3] = new Vector2(0f, 1f);
			int num9 = i * 6;
			array4[num9] = num8;
			array4[num9 + 1] = num8 + 1;
			array4[num9 + 2] = num8 + 2;
			array4[num9 + 3] = num8;
			array4[num9 + 4] = num8 + 2;
			array4[num9 + 5] = num8 + 3;
		}
		Mesh val7 = new Mesh
		{
			name = "LightMyFire_DottedRange_" + radius.ToString("0.##"),
			vertices = array,
			normals = array2,
			uv = array3,
			triangles = array4
		};
		val7.RecalculateBounds();
		return val7;
	}

	private bool IsPlacementPreviewInstance()
	{
		if (!((Component)this).gameObject.activeInHierarchy)
		{
			return false;
		}
		if ((Object)(object)_nview == (Object)null)
		{
			_nview = ((Component)this).GetComponent<ZNetView>();
		}
		if (!((Object)(object)_nview == (Object)null) && _nview.IsValid())
		{
			return _nview.GetZDO() == null;
		}
		return true;
	}

	private bool IsThisPlacementGhost()
	{
		Player localPlayer = Player.m_localPlayer;
		if ((Object)(object)localPlayer == (Object)null || PlacementGhostField == null)
		{
			return false;
		}
		try
		{
			object? value = PlacementGhostField.GetValue(localPlayer);
			GameObject val = (GameObject)((value is GameObject) ? value : null);
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			return (Object)(object)val == (Object)(object)((Component)this).gameObject || val.transform.IsChildOf(((Component)this).transform) || ((Component)this).transform.IsChildOf(val.transform);
		}
		catch
		{
			return false;
		}
	}

	private bool IsThisInventoryOpenLocally()
	{
		if ((Object)(object)_container == (Object)null)
		{
			_container = ((Component)this).GetComponent<Container>();
		}
		if ((Object)(object)_container == (Object)null)
		{
			return false;
		}
		try
		{
			InventoryGui instance = InventoryGui.instance;
			if ((Object)(object)instance != (Object)null && CurrentContainerField != null && (Object)/*isinst with value type is only supported in some contexts*/ == (Object)(object)_container)
			{
				return true;
			}
		}
		catch
		{
		}
		try
		{
			return ContainerIsInUseMethod != null && (bool)ContainerIsInUseMethod.Invoke(_container, null);
		}
		catch
		{
			return false;
		}
	}

	private void OnDisable()
	{
		if ((Object)(object)_marker != (Object)null)
		{
			_marker.SetActive(false);
		}
		_lastVisible = false;
	}
}