Decompiled source of TigerPlates v1.1.0

plugins/TigerPlates.dll

Decompiled 13 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace TigerPlates;

internal sealed class FoodMeta
{
	internal const string KeyFood = "pt.food";

	internal const string KeyFoodDur = "pt.fooddur";

	internal const string KeyFresh = "pt.foodfresh";

	private static readonly string[] Averaged = new string[2] { "pt.food", "pt.fooddur" };

	public int Quality = 1;

	public int Variant;

	public long CrafterID;

	public string CrafterName = "";

	public Dictionary<string, string> Data = new Dictionary<string, string>();

	private static Func<string, bool> _povBookkeeping;

	private static bool _povLookedUp;

	public bool HasBonuses => Data.Keys.Any((string k) => !IsBookkeeping(k));

	public static FoodMeta From(ItemData it)
	{
		return new FoodMeta
		{
			Quality = it.m_quality,
			Variant = it.m_variant,
			CrafterID = it.m_crafterID,
			CrafterName = (it.m_crafterName ?? ""),
			Data = ((it.m_customData != null) ? new Dictionary<string, string>(it.m_customData) : new Dictionary<string, string>())
		};
	}

	public FoodMeta Clone()
	{
		return new FoodMeta
		{
			Quality = Quality,
			Variant = Variant,
			CrafterID = CrafterID,
			CrafterName = CrafterName,
			Data = new Dictionary<string, string>(Data)
		};
	}

	public void ApplyTo(ItemData it)
	{
		it.m_quality = Quality;
		it.m_variant = Variant;
		it.m_crafterID = CrafterID;
		it.m_crafterName = CrafterName;
		it.m_customData = new Dictionary<string, string>(Data);
	}

	public void Write(ZPackage pkg)
	{
		pkg.Write(1);
		pkg.Write(Quality);
		pkg.Write(Variant);
		pkg.Write(CrafterID);
		pkg.Write(CrafterName ?? "");
		pkg.Write(Data.Count);
		foreach (KeyValuePair<string, string> datum in Data)
		{
			pkg.Write(datum.Key);
			pkg.Write(datum.Value ?? "");
		}
	}

	public static FoodMeta Read(ZPackage pkg)
	{
		FoodMeta foodMeta = new FoodMeta();
		if (pkg.ReadInt() != 1)
		{
			return foodMeta;
		}
		foodMeta.Quality = pkg.ReadInt();
		foodMeta.Variant = pkg.ReadInt();
		foodMeta.CrafterID = pkg.ReadLong();
		foodMeta.CrafterName = pkg.ReadString();
		int num = pkg.ReadInt();
		for (int i = 0; i < num; i++)
		{
			string key = pkg.ReadString();
			foodMeta.Data[key] = pkg.ReadString();
		}
		return foodMeta;
	}

	public ZPackage ToPackage()
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Expected O, but got Unknown
		ZPackage val = new ZPackage();
		Write(val);
		return val;
	}

	public byte[] ToBytes()
	{
		return ToPackage().GetArray();
	}

	public static FoodMeta FromBytes(byte[] bytes)
	{
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0019: Expected O, but got Unknown
		if (bytes == null || bytes.Length == 0)
		{
			return new FoodMeta();
		}
		try
		{
			return Read(new ZPackage(bytes));
		}
		catch (Exception ex)
		{
			Plugin.Log.LogWarning((object)("Unreadable crate food data, treating as plain: " + ex.Message));
			return new FoodMeta();
		}
	}

	public static bool CanMerge(FoodMeta a, FoodMeta b)
	{
		if (a.Quality != b.Quality || a.Variant != b.Variant)
		{
			return false;
		}
		bool value = Plugin.MergeFoodBonuses.Value;
		foreach (string item in a.Data.Keys.Union(b.Data.Keys))
		{
			if (!IsBookkeeping(item) && !(item == "pt.foodfresh") && (!value || !Averaged.Contains(item)))
			{
				a.Data.TryGetValue(item, out var value2);
				b.Data.TryGetValue(item, out var value3);
				if (value2 != value3)
				{
					return false;
				}
			}
		}
		bool num = a.Data.ContainsKey("pt.foodfresh");
		bool flag = b.Data.ContainsKey("pt.foodfresh");
		if (num == flag)
		{
			return true;
		}
		if (a.CrafterID != 0L)
		{
			return a.CrafterID == b.CrafterID;
		}
		return false;
	}

	public static FoodMeta Merge(FoodMeta a, int na, FoodMeta b, int nb)
	{
		if (na <= 0)
		{
			return b.Clone();
		}
		FoodMeta foodMeta = a.Clone();
		if (nb <= 0)
		{
			return foodMeta;
		}
		if (Plugin.MergeFoodBonuses.Value)
		{
			float num = na + nb;
			string[] averaged = Averaged;
			foreach (string key in averaged)
			{
				if (a.Data.ContainsKey(key) || b.Data.ContainsKey(key))
				{
					float num2 = (Val(a.Data, key) * (float)na + Val(b.Data, key) * (float)nb) / num;
					if (num2 > 0f)
					{
						foodMeta.Data[key] = num2.ToString("R", CultureInfo.InvariantCulture);
					}
					else
					{
						foodMeta.Data.Remove(key);
					}
				}
			}
		}
		if (!foodMeta.Data.ContainsKey("pt.foodfresh") && b.Data.TryGetValue("pt.foodfresh", out var value))
		{
			foodMeta.Data["pt.foodfresh"] = value;
		}
		return foodMeta;
	}

	private static float Val(Dictionary<string, string> d, string key)
	{
		if (!d.TryGetValue(key, out var value) || !float.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out var result))
		{
			return 0f;
		}
		return result;
	}

	internal static bool IsBookkeeping(string key)
	{
		if (!_povLookedUp)
		{
			_povLookedUp = true;
			try
			{
				MethodInfo methodInfo = Type.GetType("PassiveTree.StackRules, PathOfValheiman", throwOnError: false)?.GetMethod("Bookkeeping", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(string) }, null);
				if (methodInfo != null && methodInfo.ReturnType == typeof(bool))
				{
					_povBookkeeping = (Func<string, bool>)Delegate.CreateDelegate(typeof(Func<string, bool>), methodInfo);
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogDebug((object)("PoV StackRules.Bookkeeping unavailable, using built-in list: " + ex.Message));
			}
		}
		if (_povBookkeeping != null)
		{
			try
			{
				if (_povBookkeeping(key))
				{
					return true;
				}
			}
			catch
			{
				_povBookkeeping = null;
			}
		}
		switch (key)
		{
		default:
			return key.StartsWith("pt.work.", StringComparison.Ordinal);
		case "pt.born":
		case "pt.bonus":
		case "valheiman.equipment.v1.cell":
		case "pt.fish.caught":
			return true;
		}
	}
}
internal static class ItemModelBuilder
{
	private static Mesh _plateMesh;

	private const float PlateSurfaceY = 0.03f;

	private static readonly Vector2[] PlateProfile = (Vector2[])(object)new Vector2[8]
	{
		new Vector2(0f, 0.03f),
		new Vector2(0.39f, 0.03f),
		new Vector2(0.46f, 0.055f),
		new Vector2(0.5f, 0.062f),
		new Vector2(0.5f, 0.05f),
		new Vector2(0.44f, 0.015f),
		new Vector2(0.4f, 0f),
		new Vector2(0f, 0f)
	};

	public static float Build(string itemName, Transform parent, float size, float baseY = 0f, bool flatten = false)
	{
		//IL_00c2: 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_00fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0100: Unknown result type (might be due to invalid IL or missing references)
		//IL_0201: Unknown result type (might be due to invalid IL or missing references)
		//IL_0206: Unknown result type (might be due to invalid IL or missing references)
		//IL_028a: Unknown result type (might be due to invalid IL or missing references)
		//IL_028d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0293: Unknown result type (might be due to invalid IL or missing references)
		//IL_0298: Unknown result type (might be due to invalid IL or missing references)
		//IL_029d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0213: Unknown result type (might be due to invalid IL or missing references)
		//IL_0218: 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_0221: Unknown result type (might be due to invalid IL or missing references)
		//IL_0252: Unknown result type (might be due to invalid IL or missing references)
		//IL_0259: Unknown result type (might be due to invalid IL or missing references)
		//IL_022a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0231: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_02bd: 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_0269: 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_024e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0308: Unknown result type (might be due to invalid IL or missing references)
		//IL_0314: 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_02e4: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_0281: Unknown result type (might be due to invalid IL or missing references)
		//IL_0286: Unknown result type (might be due to invalid IL or missing references)
		//IL_0350: Unknown result type (might be due to invalid IL or missing references)
		//IL_035d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0364: Unknown result type (might be due to invalid IL or missing references)
		//IL_0376: Unknown result type (might be due to invalid IL or missing references)
		//IL_0387: Unknown result type (might be due to invalid IL or missing references)
		//IL_0397: Unknown result type (might be due to invalid IL or missing references)
		//IL_03a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_03b1: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = (Object.op_Implicit((Object)(object)ObjectDB.instance) ? ObjectDB.instance.GetItemPrefab(itemName) : null);
		if (!Object.op_Implicit((Object)(object)val))
		{
			return -1f;
		}
		Transform transform = val.transform;
		HashSet<Renderer> hashSet = new HashSet<Renderer>();
		LODGroup[] componentsInChildren = val.GetComponentsInChildren<LODGroup>(true);
		for (int i = 0; i < componentsInChildren.Length; i++)
		{
			LOD[] lODs = componentsInChildren[i].GetLODs();
			for (int j = 1; j < lODs.Length; j++)
			{
				Renderer[] renderers = lODs[j].renderers;
				foreach (Renderer val2 in renderers)
				{
					if (Object.op_Implicit((Object)(object)val2))
					{
						hashSet.Add(val2);
					}
				}
			}
		}
		Transform holder = new GameObject("model_" + itemName).transform;
		holder.SetParent(parent, false);
		bool any = false;
		Bounds bounds = default(Bounds);
		Matrix4x4 rootInv = transform.worldToLocalMatrix;
		MeshFilter[] componentsInChildren2 = val.GetComponentsInChildren<MeshFilter>(true);
		foreach (MeshFilter val3 in componentsInChildren2)
		{
			MeshRenderer component = ((Component)val3).GetComponent<MeshRenderer>();
			if (Object.op_Implicit((Object)(object)component) && Object.op_Implicit((Object)(object)val3.sharedMesh) && !hashSet.Contains((Renderer)(object)component) && ActiveChain(((Component)val3).transform, transform))
			{
				AddMesh(((Component)val3).transform, val3.sharedMesh, ((Renderer)component).sharedMaterials);
			}
		}
		SkinnedMeshRenderer[] componentsInChildren3 = val.GetComponentsInChildren<SkinnedMeshRenderer>(true);
		foreach (SkinnedMeshRenderer val4 in componentsInChildren3)
		{
			if (Object.op_Implicit((Object)(object)val4.sharedMesh) && !hashSet.Contains((Renderer)(object)val4) && ActiveChain(((Component)val4).transform, transform))
			{
				AddMesh(((Component)val4).transform, val4.sharedMesh, ((Renderer)val4).sharedMaterials);
			}
		}
		if (!any)
		{
			Object.Destroy((Object)(object)((Component)holder).gameObject);
			return -1f;
		}
		Quaternion val5 = Quaternion.identity;
		if (flatten)
		{
			Vector3 size2 = ((Bounds)(ref bounds)).size;
			if (size2.x < size2.y && size2.x <= size2.z)
			{
				val5 = Quaternion.Euler(0f, 0f, 90f);
			}
			else if (size2.z < size2.y && size2.z < size2.x)
			{
				val5 = Quaternion.Euler(90f, 0f, 0f);
			}
		}
		Bounds val6 = default(Bounds);
		((Bounds)(ref val6))..ctor(val5 * Corner(bounds, 0), Vector3.zero);
		for (int l = 1; l < 8; l++)
		{
			((Bounds)(ref val6)).Encapsulate(val5 * Corner(bounds, l));
		}
		float num = (flatten ? Mathf.Max(((Bounds)(ref val6)).size.x, ((Bounds)(ref val6)).size.z) : Mathf.Max(((Bounds)(ref val6)).size.x, Mathf.Max(((Bounds)(ref val6)).size.y, ((Bounds)(ref val6)).size.z)));
		if (num < 0.0001f)
		{
			Object.Destroy((Object)(object)((Component)holder).gameObject);
			return -1f;
		}
		float num2 = size / num;
		holder.localRotation = val5;
		holder.localScale = Vector3.one * num2;
		holder.localPosition = new Vector3((0f - ((Bounds)(ref val6)).center.x) * num2, baseY - ((Bounds)(ref val6)).min.y * num2, (0f - ((Bounds)(ref val6)).center.z) * num2);
		return ((Bounds)(ref val6)).size.y * num2;
		void AddMesh(Transform src, Mesh mesh, Material[] mats)
		{
			//IL_0001: 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_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0033: 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_004f: 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_0068: 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_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: 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_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: 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_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: 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)
			Matrix4x4 val7 = rootInv * src.localToWorldMatrix;
			GameObject val8 = new GameObject(((Object)src).name)
			{
				layer = ((Component)parent).gameObject.layer
			};
			Transform transform2 = val8.transform;
			transform2.SetParent(holder, false);
			transform2.localPosition = Vector4.op_Implicit(((Matrix4x4)(ref val7)).GetColumn(3));
			transform2.localRotation = ((Matrix4x4)(ref val7)).rotation;
			transform2.localScale = ((Matrix4x4)(ref val7)).lossyScale;
			val8.AddComponent<MeshFilter>().sharedMesh = mesh;
			((Renderer)val8.AddComponent<MeshRenderer>()).sharedMaterials = mats;
			Bounds bounds2 = mesh.bounds;
			for (int m = 0; m < 8; m++)
			{
				Vector3 val9 = ((Matrix4x4)(ref val7)).MultiplyPoint3x4(Corner(bounds2, m));
				if (!any)
				{
					bounds = new Bounds(val9, Vector3.zero);
					any = true;
				}
				else
				{
					((Bounds)(ref bounds)).Encapsulate(val9);
				}
			}
		}
	}

	public static float BuildPlate(Transform parent, float diameter, Material material)
	{
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_0032: 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_0046: 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)
		if ((Object)(object)_plateMesh == (Object)null)
		{
			_plateMesh = MakePlateMesh();
		}
		GameObject val = new GameObject("plate")
		{
			layer = ((Component)parent).gameObject.layer
		};
		Transform transform = val.transform;
		transform.SetParent(parent, false);
		transform.localScale = Vector3.one * diameter;
		val.AddComponent<MeshFilter>().sharedMesh = _plateMesh;
		MeshRenderer val2 = val.AddComponent<MeshRenderer>();
		if (Object.op_Implicit((Object)(object)material))
		{
			((Renderer)val2).sharedMaterial = material;
		}
		return 0.03f * diameter;
	}

	private static Mesh MakePlateMesh()
	{
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		//IL_003e: 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_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: 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_0054: 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_01c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01de: 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_01ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01fc: Expected O, but got Unknown
		//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ad: 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_00c2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c7: 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_00d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00db: 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_00f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fa: 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_010b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0110: Unknown result type (might be due to invalid IL or missing references)
		//IL_0114: Unknown result type (might be due to invalid IL or missing references)
		//IL_011f: Unknown result type (might be due to invalid IL or missing references)
		//IL_012f: 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)
		List<Vector3> list = new List<Vector3>();
		List<Vector3> list2 = new List<Vector3>();
		List<Vector2> list3 = new List<Vector2>();
		List<int> list4 = new List<int>();
		Vector2 val4 = default(Vector2);
		for (int i = 0; i < PlateProfile.Length - 1; i++)
		{
			Vector2 val = PlateProfile[i];
			Vector2 val2 = PlateProfile[i + 1];
			Vector2 val3 = val2 - val;
			Vector2 normalized = ((Vector2)(ref val3)).normalized;
			((Vector2)(ref val4))..ctor(0f - normalized.y, normalized.x);
			int count = list.Count;
			for (int j = 0; j <= 40; j++)
			{
				float num = (float)j * (float)Math.PI * 2f / 40f;
				float num2 = Mathf.Cos(num);
				float num3 = Mathf.Sin(num);
				Vector2[] array = (Vector2[])(object)new Vector2[2] { val, val2 };
				foreach (Vector2 val5 in array)
				{
					list.Add(new Vector3(val5.x * num2, val5.y, val5.x * num3));
					Vector3 val6 = new Vector3(val4.x * num2, val4.y, val4.x * num3);
					list2.Add(((Vector3)(ref val6)).normalized);
					list3.Add(new Vector2(val5.x * num2 + 0.5f, val5.x * num3 + 0.5f));
				}
			}
			for (int l = 0; l < 40; l++)
			{
				int num4 = count + l * 2;
				int i2 = num4 + 1;
				int num5 = num4 + 2;
				int i3 = num4 + 3;
				AddTri(list, list2, list4, num4, i2, num5);
				AddTri(list, list2, list4, num5, i2, i3);
			}
		}
		Mesh val7 = new Mesh
		{
			name = "tigerplate"
		};
		val7.SetVertices(list);
		val7.SetNormals(list2);
		val7.SetUVs(0, list3);
		val7.SetTriangles(list4, 0);
		val7.RecalculateBounds();
		return val7;
	}

	private static void AddTri(List<Vector3> v, List<Vector3> n, List<int> tris, int i0, int i1, int i2)
	{
		//IL_0003: 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_0017: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0054: Unknown result type (might be due to invalid IL or missing references)
		//IL_0059: Unknown result type (might be due to invalid IL or missing references)
		//IL_005e: 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_0060: Unknown result type (might be due to invalid IL or missing references)
		Vector3 val = Vector3.Cross(v[i1] - v[i0], v[i2] - v[i0]);
		if (!(((Vector3)(ref val)).sqrMagnitude < 1E-12f))
		{
			Vector3 val2 = n[i0] + n[i1] + n[i2];
			if (Vector3.Dot(val, val2) < 0f)
			{
				tris.Add(i0);
				tris.Add(i2);
				tris.Add(i1);
			}
			else
			{
				tris.Add(i0);
				tris.Add(i1);
				tris.Add(i2);
			}
		}
	}

	private static Vector3 Corner(Bounds b, int i)
	{
		//IL_0002: 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_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		return ((Bounds)(ref b)).center + Vector3.Scale(((Bounds)(ref b)).extents, new Vector3((float)(((i & 1) != 0) ? 1 : (-1)), (float)(((i & 2) != 0) ? 1 : (-1)), (float)(((i & 4) != 0) ? 1 : (-1))));
	}

	private static bool ActiveChain(Transform t, Transform root)
	{
		while ((Object)(object)t != (Object)null)
		{
			if (!((Component)t).gameObject.activeSelf)
			{
				return false;
			}
			if ((Object)(object)t == (Object)(object)root)
			{
				break;
			}
			t = t.parent;
		}
		return true;
	}
}
public class PantryCrate : MonoBehaviour, Hoverable, Interactable
{
	internal const string CrateChildName = "lpc_crate";

	internal const string ItemChildName = "lpc_item";

	private const string ZdoItem = "lynx_pc_item";

	private const string ZdoAmount = "lynx_pc_amount";

	private const string ZdoMeta = "lynx_pc_meta";

	private const string RpcAdd = "LPC_Add2";

	private const string RpcTake = "LPC_Take";

	private const string RpcClear = "LPC_Clear";

	private const string RpcGive = "LPC_Give2";

	private static int _itemMask;

	private ZNetView _nview;

	private Piece _piece;

	private Transform _itemRoot;

	private Renderer[] _crateRenderers;

	private string _shownItem;

	private int _shownVersion = -1;

	private float _nextScan;

	private readonly HashSet<ItemDrop> _seen = new HashSet<ItemDrop>();

	private static Material _plateMat;

	private static Color _plateMatColor;

	private bool Valid
	{
		get
		{
			if ((Object)(object)_nview != (Object)null)
			{
				return _nview.IsValid();
			}
			return false;
		}
	}

	private string StoredItem
	{
		get
		{
			if (!Valid)
			{
				return "";
			}
			return _nview.GetZDO().GetString("lynx_pc_item", "");
		}
	}

	private FoodMeta StoredMeta
	{
		get
		{
			if (!Valid)
			{
				return new FoodMeta();
			}
			return FoodMeta.FromBytes(_nview.GetZDO().GetByteArray("lynx_pc_meta", (byte[])null));
		}
	}

	private int StoredAmount
	{
		get
		{
			if (!Valid)
			{
				return 0;
			}
			return _nview.GetZDO().GetInt("lynx_pc_amount", 0);
		}
	}

	private static int Cap => Plugin.Capacity.Value;

	private void Awake()
	{
		_nview = ((Component)this).GetComponent<ZNetView>();
		_piece = ((Component)this).GetComponent<Piece>();
		Transform val = ((Component)this).transform.Find("lpc_crate");
		_crateRenderers = (Renderer[])(Object.op_Implicit((Object)(object)val) ? ((Array)((Component)val).GetComponentsInChildren<Renderer>(true)) : ((Array)new Renderer[0]));
		_itemRoot = ((Component)this).transform.Find("lpc_item");
		if (_itemMask == 0)
		{
			_itemMask = LayerMask.GetMask(new string[1] { "item" });
		}
		if (!((Object)(object)_nview == (Object)null) && _nview.GetZDO() != null)
		{
			_nview.Register<string, int, ZPackage>("LPC_Add2", (Action<long, string, int, ZPackage>)RPC_Add);
			_nview.Register<int>("LPC_Take", (Action<long, int>)RPC_Take);
			_nview.Register("LPC_Clear", (Action<long>)RPC_Clear);
			_nview.Register<string, int, ZPackage>("LPC_Give2", (Action<long, string, int, ZPackage>)RPC_Give);
			WearNTear component = ((Component)this).GetComponent<WearNTear>();
			if (Object.op_Implicit((Object)(object)component))
			{
				component.m_onDestroyed = (Action)Delegate.Combine(component.m_onDestroyed, new Action(OnDestroyed));
			}
			_nextScan = Time.time + Random.Range(0f, 1f);
			RefreshVisual();
		}
	}

	private void Update()
	{
		if (Valid)
		{
			if (StoredItem != _shownItem || _shownVersion != Plugin.VisualVersion)
			{
				RefreshVisual();
			}
			if (_nview.IsOwner() && Time.time >= _nextScan)
			{
				_nextScan = Time.time + Plugin.PickupInterval.Value;
				PullNearbyItems();
			}
		}
	}

	private void RefreshVisual()
	{
		string text = (_shownItem = StoredItem);
		_shownVersion = Plugin.VisualVersion;
		if (!Object.op_Implicit((Object)(object)_itemRoot))
		{
			return;
		}
		for (int num = _itemRoot.childCount - 1; num >= 0; num--)
		{
			Object.Destroy((Object)(object)((Component)_itemRoot.GetChild(num)).gameObject);
		}
		bool flag = false;
		if (!string.IsNullOrEmpty(text))
		{
			float value = Plugin.ItemDisplaySize.Value;
			float num2 = BuildPlate(value * Plugin.PlateScale.Value);
			float baseY = ((num2 > 0f) ? (num2 * 0.85f) : 0f);
			flag = ItemModelBuilder.Build(text, _itemRoot, value, baseY) > 0f;
			if (!flag)
			{
				for (int num3 = _itemRoot.childCount - 1; num3 >= 0; num3--)
				{
					Object.Destroy((Object)(object)((Component)_itemRoot.GetChild(num3)).gameObject);
				}
			}
		}
		Renderer[] crateRenderers = _crateRenderers;
		foreach (Renderer val in crateRenderers)
		{
			if (Object.op_Implicit((Object)(object)val))
			{
				val.enabled = !flag;
			}
		}
	}

	private float BuildPlate(float diameter)
	{
		if (!Plugin.ShowPlate.Value)
		{
			return 0f;
		}
		return ItemModelBuilder.BuildPlate(_itemRoot, diameter, GetPlateMaterial());
	}

	private static Material GetPlateMaterial()
	{
		//IL_0005: 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_0017: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ed: Expected O, but got Unknown
		//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
		//IL_0105: Unknown result type (might be due to invalid IL or missing references)
		//IL_013b: 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_0162: Unknown result type (might be due to invalid IL or missing references)
		Color value = Plugin.PlateColor.Value;
		if (Object.op_Implicit((Object)(object)_plateMat) && _plateMatColor == value)
		{
			return _plateMat;
		}
		Material val = null;
		foreach (string item in Plugin.SplitList(Plugin.PlateShaderItems.Value))
		{
			GameObject val2 = (Object.op_Implicit((Object)(object)ObjectDB.instance) ? ObjectDB.instance.GetItemPrefab(item) : null);
			if (!Object.op_Implicit((Object)(object)val2))
			{
				continue;
			}
			MeshRenderer[] componentsInChildren = val2.GetComponentsInChildren<MeshRenderer>(true);
			foreach (MeshRenderer val3 in componentsInChildren)
			{
				if (Object.op_Implicit((Object)(object)((Renderer)val3).sharedMaterial))
				{
					val = ((Renderer)val3).sharedMaterial;
					break;
				}
			}
			if (Object.op_Implicit((Object)(object)val))
			{
				break;
			}
		}
		if (!Object.op_Implicit((Object)(object)val))
		{
			return null;
		}
		Material val4 = new Material(val)
		{
			name = "tigerplate_wood"
		};
		val4.mainTexture = (Texture)(object)MakeWoodTexture(value);
		val4.mainTextureScale = Vector2.one;
		val4.mainTextureOffset = Vector2.zero;
		if (val4.HasProperty("_BumpMap"))
		{
			val4.SetTexture("_BumpMap", (Texture)null);
		}
		if (val4.HasProperty("_Color"))
		{
			val4.SetColor("_Color", Color.white);
		}
		if (Object.op_Implicit((Object)(object)_plateMat))
		{
			Object.Destroy((Object)(object)_plateMat);
		}
		_plateMat = val4;
		_plateMatColor = value;
		Plugin.Log.LogDebug((object)("Plate material from shader '" + ((Object)val.shader).name + "' (" + ((Object)val).name + ")"));
		return val4;
	}

	private static Texture2D MakeWoodTexture(Color baseColor)
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Expected O, but got Unknown
		//IL_010c: Unknown result type (might be due to invalid IL or missing references)
		//IL_010f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0114: Unknown result type (might be due to invalid IL or missing references)
		//IL_012c: Unknown result type (might be due to invalid IL or missing references)
		//IL_012e: Unknown result type (might be due to invalid IL or missing references)
		Texture2D val = new Texture2D(128, 128, (TextureFormat)4, true)
		{
			name = "tigerplate_wood_tex",
			wrapMode = (TextureWrapMode)1,
			filterMode = (FilterMode)1
		};
		Color[] array = (Color[])(object)new Color[16384];
		for (int i = 0; i < 128; i++)
		{
			for (int j = 0; j < 128; j++)
			{
				float num = (float)j / 127f - 0.5f;
				float num2 = (float)i / 127f - 0.5f;
				float num3 = Mathf.Sqrt(num * num + num2 * num2);
				float num4 = Mathf.Atan2(num2, num);
				float num5 = 0.012f * Mathf.Sin(num4 * 5f) + 0.006f * Mathf.Sin(num4 * 13f + 1.3f);
				float num6 = 0.5f + 0.5f * Mathf.Sin((num3 + num5) * 95f);
				num6 = Mathf.Pow(num6, 3f);
				float num7 = Mathf.PerlinNoise((float)j * 0.35f, (float)i * 0.05f);
				float num8 = 0.82f + 0.14f * num7 - 0.18f * num6;
				Color val2 = baseColor * num8;
				val2.a = 1f;
				array[i * 128 + j] = val2;
			}
		}
		val.SetPixels(array);
		val.Apply(true);
		return val;
	}

	public string GetHoverName()
	{
		ItemData itemData = GetItemData(StoredItem);
		if (itemData == null)
		{
			return _piece.m_name;
		}
		return itemData.m_shared.m_name;
	}

	public float GetHoverOffset()
	{
		return 0f;
	}

	public string GetHoverText()
	{
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		//IL_0108: Unknown result type (might be due to invalid IL or missing references)
		if (!Valid)
		{
			return "";
		}
		Localization instance = Localization.instance;
		string storedItem = StoredItem;
		int storedAmount = StoredAmount;
		if (!PrivateArea.CheckAccess(((Component)this).transform.position, 0f, false, false))
		{
			return instance.Localize(_piece.m_name + "\n$piece_noaccess");
		}
		StringBuilder stringBuilder = new StringBuilder();
		ItemData itemData = GetItemData(storedItem);
		if (itemData == null)
		{
			stringBuilder.Append(_piece.m_name).Append(" <color=#999999>($lpc_unassigned)</color>\n");
			stringBuilder.Append("[<color=yellow><b>1-8</b></color>] $lpc_assign_hint");
			return instance.Localize(stringBuilder.ToString());
		}
		stringBuilder.Append(itemData.m_shared.m_name).Append("  <color=orange>").Append(storedAmount)
			.Append("</color> / ")
			.Append(Cap)
			.Append('\n');
		stringBuilder.Append("[<color=yellow><b>$KEY_Use</b></color>] $lpc_take\n");
		stringBuilder.Append("[<color=yellow><b>$KEY_AltPlace + $KEY_Use</b></color>] $lpc_store_all");
		if (storedAmount <= 0)
		{
			stringBuilder.Append("\n[<color=yellow><b>").Append(Plugin.ClearKey.Value).Append(" + $KEY_Use</b></color>] $lpc_clear");
		}
		return instance.Localize(stringBuilder.ToString());
	}

	public bool Interact(Humanoid user, bool hold, bool alt)
	{
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		if (hold || !Valid)
		{
			return false;
		}
		Player val = (Player)(object)((user is Player) ? user : null);
		if (val == null || (Object)(object)val != (Object)(object)Player.m_localPlayer)
		{
			return false;
		}
		if (!PrivateArea.CheckAccess(((Component)this).transform.position, 0f, true, false))
		{
			return true;
		}
		string storedItem = StoredItem;
		if (ZInput.GetKey(Plugin.ClearKey.Value, false))
		{
			if (string.IsNullOrEmpty(storedItem))
			{
				return true;
			}
			if (StoredAmount > 0)
			{
				((Character)val).Message((MessageType)2, "$lpc_msg_notempty", 0, (Sprite)null, false);
				return true;
			}
			_nview.InvokeRPC("LPC_Clear", Array.Empty<object>());
			((Character)val).Message((MessageType)2, "$lpc_msg_cleared", 0, (Sprite)null, false);
			return true;
		}
		if (string.IsNullOrEmpty(storedItem))
		{
			((Character)val).Message((MessageType)2, "$lpc_assign_hint", 0, (Sprite)null, false);
			return true;
		}
		if (alt)
		{
			StoreAll(val, storedItem);
		}
		else
		{
			TakeStack(val, storedItem);
		}
		return true;
	}

	public bool UseItem(Humanoid user, ItemData item)
	{
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		if (Valid)
		{
			Player val = (Player)(object)((user is Player) ? user : null);
			if (val != null && !((Object)(object)val != (Object)(object)Player.m_localPlayer))
			{
				if (!PrivateArea.CheckAccess(((Component)this).transform.position, 0f, true, false))
				{
					return true;
				}
				if (!Plugin.IsAllowed(item))
				{
					((Character)val).Message((MessageType)2, "$lpc_msg_notfood", 0, (Sprite)null, false);
					return true;
				}
				string name = ((Object)item.m_dropPrefab).name;
				string storedItem = StoredItem;
				int num = ((!string.IsNullOrEmpty(storedItem)) ? StoredAmount : 0);
				if (!string.IsNullOrEmpty(storedItem) && storedItem != name)
				{
					ItemData itemData = GetItemData(storedItem);
					((Character)val).Message((MessageType)2, "$lpc_msg_wrongfood " + ((itemData != null) ? itemData.m_shared.m_name : storedItem), 0, (Sprite)null, false);
					return true;
				}
				FoodMeta foodMeta = FoodMeta.From(item);
				if (num > 0 && !FoodMeta.CanMerge(StoredMeta, foodMeta))
				{
					((Character)val).Message((MessageType)2, "$lpc_msg_differentbatch", 0, (Sprite)null, false);
					return true;
				}
				int num2 = Mathf.Min(item.m_stack, Cap - num);
				if (num2 <= 0)
				{
					((Character)val).Message((MessageType)2, "$lpc_msg_full", 0, (Sprite)null, false);
					return true;
				}
				((Humanoid)val).GetInventory().RemoveItem(item, num2);
				_nview.InvokeRPC("LPC_Add2", new object[3]
				{
					name,
					num2,
					foodMeta.ToPackage()
				});
				return true;
			}
		}
		return false;
	}

	private void TakeStack(Player player, string item)
	{
		int storedAmount = StoredAmount;
		if (storedAmount <= 0)
		{
			((Character)player).Message((MessageType)2, "$lpc_msg_empty", 0, (Sprite)null, false);
			return;
		}
		ItemData itemData = GetItemData(item);
		if (itemData != null)
		{
			int want = Mathf.Min(storedAmount, itemData.m_shared.m_maxStackSize);
			int num = RoomFor(((Humanoid)player).GetInventory(), itemData, StoredMeta, want);
			if (num <= 0)
			{
				((Character)player).Message((MessageType)2, "$lpc_msg_invfull", 0, (Sprite)null, false);
				return;
			}
			_nview.InvokeRPC("LPC_Take", new object[1] { num });
		}
	}

	private void StoreAll(Player player, string item)
	{
		Inventory inventory = ((Humanoid)player).GetInventory();
		int num = StoredAmount;
		if (num >= Cap)
		{
			((Character)player).Message((MessageType)2, "$lpc_msg_full", 0, (Sprite)null, false);
			return;
		}
		FoodMeta a = StoredMeta;
		int num2 = 0;
		int num3 = 0;
		foreach (ItemData item2 in new List<ItemData>(inventory.GetAllItems()))
		{
			if (num >= Cap)
			{
				break;
			}
			if (!((Object)(object)item2.m_dropPrefab == (Object)null) && !(((Object)item2.m_dropPrefab).name != item) && !item2.m_equipped)
			{
				FoodMeta foodMeta = FoodMeta.From(item2);
				if (num > 0 && !FoodMeta.CanMerge(a, foodMeta))
				{
					num3++;
					continue;
				}
				int num4 = Mathf.Min(item2.m_stack, Cap - num);
				inventory.RemoveItem(item2, num4);
				_nview.InvokeRPC("LPC_Add2", new object[3]
				{
					item,
					num4,
					foodMeta.ToPackage()
				});
				a = FoodMeta.Merge(a, num, foodMeta, num4);
				num += num4;
				num2 += num4;
			}
		}
		if (num2 <= 0)
		{
			((Character)player).Message((MessageType)2, (num3 > 0) ? "$lpc_msg_differentbatch" : "$lpc_msg_nothing", 0, (Sprite)null, false);
		}
	}

	private static int RoomFor(Inventory inv, ItemData template, FoodMeta meta, int want)
	{
		int maxStackSize = template.m_shared.m_maxStackSize;
		int num = inv.GetEmptySlots() * maxStackSize;
		foreach (ItemData allItem in inv.GetAllItems())
		{
			if (num >= want)
			{
				return want;
			}
			if (!(allItem.m_shared.m_name != template.m_shared.m_name))
			{
				FoodMeta foodMeta = FoodMeta.From(allItem);
				if (foodMeta.Quality == meta.Quality && foodMeta.Variant == meta.Variant && foodMeta.Data.Count == meta.Data.Count && !foodMeta.Data.Except(meta.Data).Any())
				{
					num += Mathf.Max(0, maxStackSize - allItem.m_stack);
				}
			}
		}
		return Mathf.Min(num, want);
	}

	private void RPC_Add(long sender, string item, int amount, ZPackage metaPkg)
	{
		if (_nview.IsOwner() && amount > 0)
		{
			FoodMeta foodMeta = FoodMeta.Read(metaPkg);
			int num = AcceptOwner(item, amount, foodMeta);
			int num2 = amount - num;
			if (num2 > 0)
			{
				_nview.InvokeRPC(sender, "LPC_Give2", new object[3]
				{
					item,
					num2,
					foodMeta.ToPackage()
				});
			}
		}
	}

	private int AcceptOwner(string item, int amount, FoodMeta incoming)
	{
		ZDO zDO = _nview.GetZDO();
		string text = zDO.GetString("lynx_pc_item", "");
		int num = zDO.GetInt("lynx_pc_amount", 0);
		if (!string.IsNullOrEmpty(text) && text != item)
		{
			return 0;
		}
		if (string.IsNullOrEmpty(text))
		{
			num = 0;
		}
		FoodMeta a = FoodMeta.FromBytes(zDO.GetByteArray("lynx_pc_meta", (byte[])null));
		if (num > 0 && !FoodMeta.CanMerge(a, incoming))
		{
			return 0;
		}
		int num2 = Mathf.Clamp(Cap - num, 0, amount);
		if (num2 <= 0)
		{
			return 0;
		}
		if (string.IsNullOrEmpty(text))
		{
			zDO.Set("lynx_pc_item", item);
		}
		zDO.Set("lynx_pc_meta", FoodMeta.Merge(a, num, incoming, num2).ToBytes());
		zDO.Set("lynx_pc_amount", num + num2);
		return num2;
	}

	private void RPC_Take(long sender, int want)
	{
		if (_nview.IsOwner() && want > 0)
		{
			ZDO zDO = _nview.GetZDO();
			string text = zDO.GetString("lynx_pc_item", "");
			int num = zDO.GetInt("lynx_pc_amount", 0);
			int num2 = Mathf.Min(want, num);
			if (!string.IsNullOrEmpty(text) && num2 > 0)
			{
				zDO.Set("lynx_pc_amount", num - num2);
				FoodMeta foodMeta = FoodMeta.FromBytes(zDO.GetByteArray("lynx_pc_meta", (byte[])null));
				_nview.InvokeRPC(sender, "LPC_Give2", new object[3]
				{
					text,
					num2,
					foodMeta.ToPackage()
				});
			}
		}
	}

	private void RPC_Clear(long sender)
	{
		if (_nview.IsOwner())
		{
			ZDO zDO = _nview.GetZDO();
			if (zDO.GetInt("lynx_pc_amount", 0) <= 0)
			{
				zDO.Set("lynx_pc_item", "");
				zDO.Set("lynx_pc_amount", 0);
				zDO.Set("lynx_pc_meta", new byte[0]);
			}
		}
	}

	private void RPC_Give(long sender, string item, int amount, ZPackage metaPkg)
	{
		Player localPlayer = Player.m_localPlayer;
		if (Object.op_Implicit((Object)(object)localPlayer) && amount > 0)
		{
			GiveToPlayer(localPlayer, item, amount, FoodMeta.Read(metaPkg));
		}
	}

	private static ItemData MakeItem(GameObject prefab, ItemDrop drop, int n, FoodMeta meta)
	{
		ItemData val = drop.m_itemData.Clone();
		val.m_dropPrefab = prefab;
		val.m_stack = n;
		val.m_worldLevel = Game.m_worldLevel;
		meta.ApplyTo(val);
		return val;
	}

	private static void GiveToPlayer(Player player, string item, int amount, FoodMeta meta)
	{
		//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_00e1: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = (Object.op_Implicit((Object)(object)ObjectDB.instance) ? ObjectDB.instance.GetItemPrefab(item) : null);
		ItemDrop val2 = (Object.op_Implicit((Object)(object)val) ? val.GetComponent<ItemDrop>() : null);
		if (!Object.op_Implicit((Object)(object)val2))
		{
			Plugin.Log.LogWarning((object)$"Unknown item '{item}' while giving {amount}; lost");
			return;
		}
		Inventory inventory = ((Humanoid)player).GetInventory();
		int num = Mathf.Max(1, val2.m_itemData.m_shared.m_maxStackSize);
		int num2 = amount;
		while (num2 > 0)
		{
			int num3 = Mathf.Min(num2, num);
			ItemData val3 = MakeItem(val, val2, num3, meta);
			if (inventory.CanAddItem(val3, num3) && inventory.AddItem(val3))
			{
				((Character)player).ShowPickupMessage(val3, num3);
			}
			else
			{
				Transform transform = ((Component)player).transform;
				ItemDrop.DropItem(val3, num3, transform.position + transform.forward * 0.6f + Vector3.up, transform.rotation);
			}
			num2 -= num3;
		}
	}

	private void PullNearbyItems()
	{
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		float value = Plugin.PickupRadius.Value;
		string storedItem = StoredItem;
		if (value <= 0f || string.IsNullOrEmpty(storedItem) || StoredAmount >= Cap)
		{
			return;
		}
		_seen.Clear();
		Collider[] array = Physics.OverlapSphere(((Component)this).transform.position, value, _itemMask);
		for (int i = 0; i < array.Length; i++)
		{
			ItemDrop componentInParent = ((Component)array[i]).GetComponentInParent<ItemDrop>();
			if (!Object.op_Implicit((Object)(object)componentInParent) || !_seen.Add(componentInParent) || Utils.GetPrefabName(((Component)componentInParent).gameObject) != storedItem)
			{
				continue;
			}
			ZNetView component = ((Component)componentInParent).GetComponent<ZNetView>();
			if ((Object)(object)component == (Object)null || !component.IsValid())
			{
				continue;
			}
			int storedAmount = StoredAmount;
			int stack = componentInParent.m_itemData.m_stack;
			if (storedAmount + stack > Cap)
			{
				continue;
			}
			FoodMeta foodMeta = FoodMeta.From(componentInParent.m_itemData);
			if (storedAmount > 0 && !FoodMeta.CanMerge(StoredMeta, foodMeta))
			{
				continue;
			}
			if (!componentInParent.CanPickup(true))
			{
				if (!component.IsOwner())
				{
					componentInParent.RequestOwn();
				}
			}
			else if (AcceptOwner(storedItem, stack, foodMeta) == stack)
			{
				ZNetScene.instance.Destroy(((Component)componentInParent).gameObject);
			}
		}
	}

	private void OnDestroyed()
	{
		//IL_0095: Unknown result type (might be due to invalid IL or missing references)
		//IL_009a: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ae: 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_00bd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
		if (!Valid || !_nview.IsOwner())
		{
			return;
		}
		string storedItem = StoredItem;
		int num = StoredAmount;
		if (string.IsNullOrEmpty(storedItem) || num <= 0)
		{
			return;
		}
		GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(storedItem);
		ItemDrop val = (Object.op_Implicit((Object)(object)itemPrefab) ? itemPrefab.GetComponent<ItemDrop>() : null);
		if (Object.op_Implicit((Object)(object)val))
		{
			FoodMeta storedMeta = StoredMeta;
			int num2 = Mathf.Max(1, val.m_itemData.m_shared.m_maxStackSize);
			while (num > 0)
			{
				int num3 = Mathf.Min(num, num2);
				ItemData obj = MakeItem(itemPrefab, val, num3, storedMeta);
				Vector3 val2 = ((Component)this).transform.position + Vector3.up * 0.5f + Random.insideUnitSphere * 0.3f;
				ItemDrop.DropItem(obj, num3, val2, Quaternion.Euler(0f, Random.Range(0f, 360f), 0f));
				num -= num3;
			}
			_nview.GetZDO().Set("lynx_pc_amount", 0);
		}
	}

	private static ItemData GetItemData(string item)
	{
		if (string.IsNullOrEmpty(item) || !Object.op_Implicit((Object)(object)ObjectDB.instance))
		{
			return null;
		}
		GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(item);
		ItemDrop val = (Object.op_Implicit((Object)(object)itemPrefab) ? itemPrefab.GetComponent<ItemDrop>() : null);
		if (!Object.op_Implicit((Object)(object)val))
		{
			return null;
		}
		return val.m_itemData;
	}
}
[BepInPlugin("lynx.tigerplates", "TigerPlates", "1.1.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
public class Plugin : BaseUnityPlugin
{
	[HarmonyPatch(typeof(Player), "OnSpawned")]
	private static class PlayerOnSpawnedPatch
	{
		private static void Postfix()
		{
			RegisterInBuildTools();
		}
	}

	public const string Guid = "lynx.tigerplates";

	public const string ModName = "TigerPlates";

	public const string Version = "1.1.0";

	public const string BuildLabel = "1.1.0";

	public const string PrefabName = "lynx_pantrycrate";

	private const string BasePrefab = "piece_chest_wood";

	internal static Plugin Instance;

	internal static ManualLogSource Log;

	internal static ConfigEntry<int> Capacity;

	internal static ConfigEntry<float> PickupRadius;

	internal static ConfigEntry<float> PickupInterval;

	internal static ConfigEntry<float> ItemDisplaySize;

	internal static ConfigEntry<float> CrateScale;

	internal static ConfigEntry<bool> ShowPlate;

	internal static ConfigEntry<Color> PlateColor;

	internal static ConfigEntry<float> PlateScale;

	internal static ConfigEntry<string> PlateShaderItems;

	internal static ConfigEntry<string> BuildTools;

	internal static ConfigEntry<string> BuildToolNameMatch;

	internal static ConfigEntry<string> ExtraAllowedItems;

	internal static ConfigEntry<string> DeniedItems;

	internal static ConfigEntry<bool> MergeFoodBonuses;

	internal static ConfigEntry<string> BuildCost;

	internal static ConfigEntry<KeyCode> ClearKey;

	internal static int VisualVersion;

	private static GameObject _prefab;

	private Harmony _harmony;

	private void Awake()
	{
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: Expected O, but got Unknown
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0057: Expected O, but got Unknown
		//IL_008f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0099: 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
		//IL_0105: Unknown result type (might be due to invalid IL or missing references)
		//IL_010f: Expected O, but got Unknown
		//IL_0139: Unknown result type (might be due to invalid IL or missing references)
		//IL_0143: Expected O, but got Unknown
		//IL_0169: Unknown result type (might be due to invalid IL or missing references)
		//IL_0173: Expected O, but got Unknown
		//IL_019d: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a7: Expected O, but got Unknown
		//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01db: Expected O, but got Unknown
		//IL_0205: Unknown result type (might be due to invalid IL or missing references)
		//IL_020f: Expected O, but got Unknown
		//IL_0242: Unknown result type (might be due to invalid IL or missing references)
		//IL_024c: Expected O, but got Unknown
		//IL_0295: Unknown result type (might be due to invalid IL or missing references)
		//IL_02fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0305: Expected O, but got Unknown
		//IL_0338: Unknown result type (might be due to invalid IL or missing references)
		//IL_0342: Expected O, but got Unknown
		//IL_03f8: Unknown result type (might be due to invalid IL or missing references)
		//IL_0402: Expected O, but got Unknown
		Instance = this;
		Log = ((BaseUnityPlugin)this).Logger;
		ConfigurationManagerAttributes val = new ConfigurationManagerAttributes
		{
			IsAdminOnly = true
		};
		Capacity = ((BaseUnityPlugin)this).Config.Bind<int>("General", "Capacity", 2000, new ConfigDescription("Maximum number of items one crate can hold.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 100000), new object[1] { val }));
		PickupRadius = ((BaseUnityPlugin)this).Config.Bind<float>("General", "PickupRadius", 40f, new ConfigDescription("Radius (m) in which a crate pulls in loose items matching its food. 0 disables.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), new object[1] { val }));
		PickupInterval = ((BaseUnityPlugin)this).Config.Bind<float>("General", "PickupInterval", 1f, new ConfigDescription("Seconds between pickup scans.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.25f, 10f), new object[1] { val }));
		ExtraAllowedItems = ((BaseUnityPlugin)this).Config.Bind<string>("Items", "ExtraAllowedItems", "", new ConfigDescription("Comma-separated item prefab names to allow even though they aren't edible (e.g. Turnip,Onion).", (AcceptableValueBase)null, new object[1] { val }));
		DeniedItems = ((BaseUnityPlugin)this).Config.Bind<string>("Items", "DeniedItems", "", new ConfigDescription("Comma-separated item prefab names to refuse even though they're edible.", (AcceptableValueBase)null, new object[1] { val }));
		MergeFoodBonuses = ((BaseUnityPlugin)this).Config.Bind<bool>("Items", "MergeFoodBonuses", true, new ConfigDescription("Path of Valheiman cooking bonuses (nourishment, duration) on food going into a crate are averaged by count, like LynxModFixes' MergeCookedFoodStacks. Off = a crate only takes food with exactly the same bonuses as what's already in it.", (AcceptableValueBase)null, new object[1] { val }));
		BuildCost = ((BaseUnityPlugin)this).Config.Bind<string>("Building", "BuildCost", "Wood:4", new ConfigDescription("Build cost as Item:Amount pairs, comma-separated. Applied on next world load.", (AcceptableValueBase)null, new object[1] { val }));
		BuildTools = ((BaseUnityPlugin)this).Config.Bind<string>("Building", "BuildToolPrefabs", "Feaster", new ConfigDescription("Comma-separated tool item prefab names whose build menu gets the crate. Feaster = vanilla Serving Tray.", (AcceptableValueBase)null, new object[1] { val }));
		BuildToolNameMatch = ((BaseUnityPlugin)this).Config.Bind<string>("Building", "BuildToolNameMatch", "keg hammer", new ConfigDescription("Comma-separated text matched (case-insensitive) against tool display names and prefab names; matching build tools also get the crate. Catches Valheim Cuisine's Keg Hammer.", (AcceptableValueBase)null, new object[1] { val }));
		ItemDisplaySize = ((BaseUnityPlugin)this).Config.Bind<float>("Visual", "ItemDisplaySize", 0.45f, new ConfigDescription("Largest dimension (m) of the food model shown on an assigned crate.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 2f), Array.Empty<object>()));
		ShowPlate = ((BaseUnityPlugin)this).Config.Bind<bool>("Visual", "ShowPlate", true, "Show a wooden plate under the food on assigned crates.");
		PlateColor = ((BaseUnityPlugin)this).Config.Bind<Color>("Visual", "PlateColor", new Color(0.42f, 0.28f, 0.16f, 1f), "Colour of the plate.");
		PlateShaderItems = ((BaseUnityPlugin)this).Config.Bind<string>("Visual", "PlateShaderSource", "Wood,FineWood,Carrot", "Item prefabs (tried in order) whose material shader the plate borrows. Only change this if the plate renders oddly.");
		PlateScale = ((BaseUnityPlugin)this).Config.Bind<float>("Visual", "PlateScale", 1.25f, new ConfigDescription("Plate width relative to ItemDisplaySize.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 3f), Array.Empty<object>()));
		CrateScale = ((BaseUnityPlugin)this).Config.Bind<float>("Visual", "EmptyCrateScale", 0.4f, new ConfigDescription("Scale of the empty crate relative to a vanilla wood chest. Applied on game restart.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 1f), Array.Empty<object>()));
		ClearKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Controls", "ClearModifier", (KeyCode)306, "Hold this while pressing Use on an EMPTY crate to clear its assigned food.");
		ConfigEntryBase[] array = (ConfigEntryBase[])(object)new ConfigEntryBase[4]
		{
			(ConfigEntryBase)ShowPlate,
			(ConfigEntryBase)PlateColor,
			(ConfigEntryBase)PlateScale,
			(ConfigEntryBase)ItemDisplaySize
		};
		foreach (ConfigEntryBase e in array)
		{
			e.ConfigFile.SettingChanged += delegate(object _, SettingChangedEventArgs a)
			{
				if (a.ChangedSetting == e)
				{
					VisualVersion++;
				}
			};
		}
		AddLocalization();
		PrefabManager.OnVanillaPrefabsAvailable += CreatePrefab;
		PieceManager.OnPiecesRegistered += RegisterInBuildTools;
		_harmony = new Harmony("lynx.tigerplates");
		_harmony.PatchAll(typeof(Plugin).Assembly);
		Log.LogInfo((object)"TigerPlates 1.1.0 loaded");
	}

	private static void AddLocalization()
	{
		CustomLocalization localization = LocalizationManager.Instance.GetLocalization();
		string text = "English";
		localization.AddTranslation(ref text, new Dictionary<string, string>
		{
			{ "piece_lynx_pantrycrate", "Pantry Crate" },
			{ "piece_lynx_pantrycrate_desc", "Holds a large supply of one food. It takes on the look of whatever it holds and gathers up matching food lying nearby." },
			{ "lpc_unassigned", "Empty" },
			{ "lpc_assign_hint", "Use a food from your hotbar on it to assign" },
			{ "lpc_take", "Take a stack" },
			{ "lpc_store_all", "Store all" },
			{ "lpc_clear", "Clear food" },
			{ "lpc_msg_notfood", "Only food can go in a pantry crate" },
			{ "lpc_msg_wrongfood", "This crate holds" },
			{ "lpc_msg_full", "The crate is full" },
			{ "lpc_msg_empty", "The crate is empty" },
			{ "lpc_msg_notempty", "Empty the crate before clearing it" },
			{ "lpc_msg_cleared", "Crate cleared" },
			{ "lpc_msg_invfull", "No room in your inventory" },
			{ "lpc_msg_nothing", "You have none to store" },
			{ "lpc_msg_differentbatch", "This batch was cooked differently from what's in the crate" }
		});
	}

	private void CreatePrefab()
	{
		//IL_0071: 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_00b4: Expected O, but got Unknown
		//IL_0118: Unknown result type (might be due to invalid IL or missing references)
		//IL_0127: Unknown result type (might be due to invalid IL or missing references)
		//IL_0136: 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_0192: Unknown result type (might be due to invalid IL or missing references)
		PrefabManager.OnVanillaPrefabsAvailable -= CreatePrefab;
		try
		{
			_prefab = PrefabManager.Instance.CreateClonedPrefab("lynx_pantrycrate", "piece_chest_wood");
			if (!Object.op_Implicit((Object)(object)_prefab))
			{
				Log.LogError((object)"Could not clone piece_chest_wood; Pantry Crate disabled");
				return;
			}
			Container[] componentsInChildren = _prefab.GetComponentsInChildren<Container>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren[i]);
			}
			Transform transform = new GameObject("lpc_crate").transform;
			transform.SetParent(_prefab.transform, false);
			List<Transform> list = new List<Transform>();
			foreach (Transform item in _prefab.transform)
			{
				Transform val = item;
				if ((Object)(object)val != (Object)(object)transform)
				{
					list.Add(val);
				}
			}
			foreach (Transform item2 in list)
			{
				item2.SetParent(transform, false);
			}
			transform.localScale = Vector3.one * CrateScale.Value;
			Transform transform2 = new GameObject("lpc_item").transform;
			transform2.SetParent(_prefab.transform, false);
			((Component)transform2).gameObject.layer = _prefab.layer;
			Piece component = _prefab.GetComponent<Piece>();
			component.m_name = "$piece_lynx_pantrycrate";
			component.m_description = "$piece_lynx_pantrycrate_desc";
			component.m_category = (PieceCategory)0;
			component.m_usage = (UsageTagFlags)5121;
			component.m_craftingStation = null;
			component.m_resources = (Requirement[])(object)new Requirement[0];
			component.m_groundOnly = false;
			component.m_comfort = 0;
			_prefab.AddComponent<PantryCrate>();
			PrefabManager.Instance.AddPrefab(_prefab);
			Log.LogDebug((object)("Pantry Crate prefab components: " + string.Join(", ", from c in _prefab.GetComponents<Component>()
				select ((object)c).GetType().Name)));
		}
		catch (Exception arg)
		{
			Log.LogError((object)$"Failed to create Pantry Crate prefab: {arg}");
		}
	}

	internal static void RegisterInBuildTools()
	{
		if (!Object.op_Implicit((Object)(object)_prefab) || !Object.op_Implicit((Object)(object)ObjectDB.instance))
		{
			return;
		}
		_prefab.GetComponent<Piece>().m_resources = ParseCost(BuildCost.Value);
		List<string> list = SplitList(BuildTools.Value);
		List<string> list2 = (from s in SplitList(BuildToolNameMatch.Value)
			select s.ToLowerInvariant()).ToList();
		foreach (GameObject item in ObjectDB.instance.m_items)
		{
			if (!Object.op_Implicit((Object)(object)item))
			{
				continue;
			}
			ItemDrop component = item.GetComponent<ItemDrop>();
			PieceTable val = component?.m_itemData?.m_shared?.m_buildPieces;
			if ((Object)(object)val == (Object)null)
			{
				continue;
			}
			bool flag = list.Contains(((Object)item).name);
			if (!flag && list2.Count > 0)
			{
				string display = ((Localization.instance != null) ? Localization.instance.Localize(component.m_itemData.m_shared.m_name).ToLowerInvariant() : "");
				string pname = ((Object)item).name.ToLowerInvariant();
				flag = list2.Any((string m) => display.Contains(m) || pname.Contains(m.Replace(" ", "")));
			}
			if (flag && !val.m_pieces.Contains(_prefab))
			{
				val.m_pieces.Add(_prefab);
				Log.LogInfo((object)("Added Pantry Crate to build tool " + ((Object)item).name + " (" + ((Object)val).name + ")"));
			}
		}
	}

	private static Requirement[] ParseCost(string cost)
	{
		//IL_0092: Unknown result type (might be due to invalid IL or missing references)
		//IL_0097: Unknown result type (might be due to invalid IL or missing references)
		//IL_009f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b2: Expected O, but got Unknown
		List<Requirement> list = new List<Requirement>();
		foreach (string item in SplitList(cost))
		{
			string[] array = item.Split(':');
			if (array.Length == 2 && int.TryParse(array[1].Trim(), out var result))
			{
				GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(array[0].Trim());
				ItemDrop val = (Object.op_Implicit((Object)(object)itemPrefab) ? itemPrefab.GetComponent<ItemDrop>() : null);
				if (!Object.op_Implicit((Object)(object)val))
				{
					Log.LogWarning((object)("BuildCost: unknown item '" + array[0] + "'"));
					continue;
				}
				list.Add(new Requirement
				{
					m_resItem = val,
					m_amount = result,
					m_recover = true
				});
			}
		}
		return list.ToArray();
	}

	internal static List<string> SplitList(string s)
	{
		return (from x in (s ?? "").Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries)
			select x.Trim() into x
			where x.Length > 0
			select x).ToList();
	}

	internal static bool IsAllowed(ItemData item)
	{
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_006a: Invalid comparison between Unknown and I4
		if (item == null || (Object)(object)item.m_dropPrefab == (Object)null)
		{
			return false;
		}
		string name = ((Object)item.m_dropPrefab).name;
		if (SplitList(DeniedItems.Value).Contains(name))
		{
			return false;
		}
		if (SplitList(ExtraAllowedItems.Value).Contains(name))
		{
			return true;
		}
		SharedData shared = item.m_shared;
		if (shared.m_maxStackSize <= 1)
		{
			return false;
		}
		if ((int)shared.m_itemType == 2)
		{
			if (!(shared.m_food > 0f) && !(shared.m_foodStamina > 0f))
			{
				return shared.m_foodEitr > 0f;
			}
			return true;
		}
		return false;
	}
}