Decompiled source of FeastPortions v0.1.1

FeastPortions.dll

Decompiled 2 days ago
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace FeastPortions;

[BepInPlugin("j1ga.feastportions", "FeastPortions", "0.1.1")]
public class FeastPortionsPlugin : BaseUnityPlugin
{
	private sealed class FeastInfo
	{
		public GameObject Piece;

		public ItemDrop Food;

		public int Portions;

		public GameObject Portion;

		public SharedData Shared;
	}

	private sealed class Bite
	{
		public float Time;

		public bool Take;

		public int Need;

		public bool Given;

		public bool Last;
	}

	[HarmonyPatch(typeof(Container), "Awake")]
	private static class Container_Awake_Patch
	{
		private static void Postfix(Container __instance)
		{
			Inventory inventory = __instance.GetInventory();
			if (inventory == null)
			{
				return;
			}
			if (_containers.Count > 4000)
			{
				List<Inventory> list = new List<Inventory>();
				foreach (KeyValuePair<Inventory, Container> container in _containers)
				{
					if ((Object)(object)container.Value == (Object)null)
					{
						list.Add(container.Key);
					}
				}
				foreach (Inventory item in list)
				{
					_containers.Remove(item);
				}
			}
			_containers[inventory] = __instance;
		}
	}

	[HarmonyPatch(typeof(Inventory), "AddItem", new Type[] { typeof(ItemData) })]
	private static class Inventory_AddItem_Patch
	{
		private static bool Prefix(Inventory __instance, ItemData item, ref bool __result)
		{
			if (!KeptOut(__instance, item))
			{
				return true;
			}
			__result = false;
			return false;
		}
	}

	[HarmonyPatch(typeof(Inventory), "AddItem", new Type[]
	{
		typeof(ItemData),
		typeof(Vector2i)
	})]
	private static class Inventory_AddItemAt_Patch
	{
		private static bool Prefix(Inventory __instance, ItemData item, ref bool __result)
		{
			if (!KeptOut(__instance, item))
			{
				return true;
			}
			__result = false;
			return false;
		}
	}

	[HarmonyPatch(typeof(Inventory), "AddItem", new Type[]
	{
		typeof(ItemData),
		typeof(int),
		typeof(int),
		typeof(int),
		typeof(bool)
	})]
	private static class Inventory_AddItemXY_Patch
	{
		private static bool Prefix(Inventory __instance, ItemData item, ref bool __result)
		{
			if (!KeptOut(__instance, item))
			{
				return true;
			}
			__result = false;
			return false;
		}
	}

	[HarmonyPatch(typeof(InventoryGrid), "DropItem")]
	private static class InventoryGrid_DropItem_Patch
	{
		private static bool Prefix(InventoryGrid __instance, Inventory fromInventory, Vector2i pos, ref bool __result)
		{
			Inventory inventory = __instance.GetInventory();
			if (inventory == null || inventory == fromInventory)
			{
				return true;
			}
			ItemData itemAt = inventory.GetItemAt(pos.x, pos.y);
			if (itemAt == null || !KeptOut(fromInventory, itemAt))
			{
				return true;
			}
			__result = false;
			return false;
		}
	}

	[HarmonyPatch(typeof(ObjectDB), "Awake")]
	private static class ObjectDB_Awake_Patch
	{
		private static void Postfix(ObjectDB __instance)
		{
			Register(__instance);
		}
	}

	[HarmonyPatch(typeof(ObjectDB), "CopyOtherDB")]
	private static class ObjectDB_CopyOtherDB_Patch
	{
		private static void Postfix(ObjectDB __instance)
		{
			Register(__instance);
		}
	}

	[HarmonyPatch(typeof(ZNetScene), "Awake")]
	private static class ZNetScene_Awake_Patch
	{
		private static void Postfix(ZNetScene __instance)
		{
			Register(__instance);
		}
	}

	[HarmonyPatch(typeof(Inventory), "Load", new Type[] { typeof(ZPackage) })]
	private static class Inventory_Load_Patch
	{
		private static void Postfix(Inventory __instance)
		{
			foreach (ItemData allItem in __instance.GetAllItems())
			{
				if (allItem != null && !((Object)(object)allItem.m_dropPrefab == (Object)null) && _byFood.TryGetValue(((Object)allItem.m_dropPrefab).name, out var value))
				{
					allItem.m_shared = value.Shared;
					allItem.m_dropPrefab = value.Portion;
				}
			}
		}
	}

	[HarmonyPatch(typeof(Feast), "Interact")]
	private static class Feast_Interact_Patch
	{
		private static bool Prefix(Feast __instance, Humanoid human, bool hold, bool alt, ref bool __result)
		{
			//IL_005f: 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_00c8: 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)
			ZNetView component = ((Component)__instance).GetComponent<ZNetView>();
			if ((Object)(object)component == (Object)null || !component.IsValid() || hold)
			{
				return true;
			}
			int num = PortionsLeft(__instance);
			Bite bite = new Bite();
			bite.Time = Time.time;
			bite.Last = num == 1;
			int num2 = Cost();
			if (!alt || !_takePortions.Value)
			{
				_bites[component.GetZDO().m_uid] = bite;
				return true;
			}
			__result = false;
			Player val = (Player)(object)((human is Player) ? human : null);
			if ((Object)(object)val == (Object)null || (Object)(object)val != (Object)(object)Player.m_localPlayer || num <= 0)
			{
				return false;
			}
			if (num < num2)
			{
				((Character)val).Message((MessageType)2, T("Too little left to take - eat it here", "Слишком мало, чтобы взять с собой — съешьте здесь"), 0, (Sprite)null, false);
				return false;
			}
			if (Vector3.Distance(((Component)val).transform.position, ((Component)__instance).transform.position) >= __instance.m_useDistance)
			{
				return false;
			}
			FeastInfo feastInfo = InfoOf(__instance);
			if (feastInfo == null)
			{
				return false;
			}
			if (!((Humanoid)val).GetInventory().CanAddItem(feastInfo.Portion, 1))
			{
				((Character)val).Message((MessageType)2, "$inventory_full", 0, (Sprite)null, false);
				return false;
			}
			bite.Take = true;
			bite.Need = num2;
			bite.Last = num == num2;
			_bites[component.GetZDO().m_uid] = bite;
			for (int i = 0; i < num2; i++)
			{
				component.InvokeRPC("RPC_TryEat", new object[0]);
			}
			__result = true;
			return false;
		}
	}

	[HarmonyPatch(typeof(Feast), "RPC_EatConfirmation")]
	private static class Feast_RPC_EatConfirmation_Patch
	{
		private static bool Prefix(Feast __instance, out Bite __state)
		{
			//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_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			__state = null;
			ZNetView component = ((Component)__instance).GetComponent<ZNetView>();
			if ((Object)(object)component == (Object)null || !component.IsValid())
			{
				return true;
			}
			ZDOID uid = component.GetZDO().m_uid;
			if (!_bites.TryGetValue(uid, out var value))
			{
				return true;
			}
			if (Time.time - value.Time > 5f)
			{
				_bites.Remove(uid);
				return true;
			}
			if (!value.Take)
			{
				_bites.Remove(uid);
				__state = value;
				return true;
			}
			value.Need--;
			if (value.Need <= 0)
			{
				_bites.Remove(uid);
				__state = value;
			}
			if (value.Given)
			{
				return false;
			}
			value.Given = true;
			Player localPlayer = Player.m_localPlayer;
			FeastInfo feastInfo = InfoOf(__instance);
			if ((Object)(object)localPlayer == (Object)null || feastInfo == null)
			{
				return false;
			}
			if (Give(localPlayer, feastInfo, 1) > 0)
			{
				((Character)localPlayer).Message((MessageType)1, "$msg_added " + feastInfo.Shared.m_name, 1, feastInfo.Shared.m_icons[0], false);
			}
			return false;
		}

		private static void Postfix(Feast __instance, Bite __state)
		{
			if (__state != null && __state.Last)
			{
				RemoveEmpty(__instance);
			}
		}
	}

	[HarmonyPatch(typeof(Feast), "GetHoverText")]
	private static class Feast_GetHoverText_Patch
	{
		private static void Postfix(Feast __instance, ref string __result)
		{
			//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)
			if (_takePortions.Value && !string.IsNullOrEmpty(__result) && !((Object)(object)Player.m_localPlayer == (Object)null) && !(Vector3.Distance(((Component)Player.m_localPlayer).transform.position, ((Component)__instance).transform.position) >= __instance.m_useDistance))
			{
				int num = Cost();
				string text = T("Take a portion", "Взять кусочек") + ((num > 1) ? T(" (" + num + " servings)", " (" + num + " куска)") : "");
				if (PortionsLeft(__instance) < num)
				{
					__result = __result + "\n<color=#888888>" + text + "</color>";
				}
				else
				{
					__result = __result + Localization.instance.Localize("\n[<color=yellow><b>$KEY_AltPlace + $KEY_Use</b></color>] ") + text;
				}
			}
		}
	}

	[HarmonyPatch(typeof(Humanoid), "DropItem")]
	private static class Humanoid_DropItem_Patch
	{
		private static bool Prefix(Humanoid __instance, Inventory inventory, ItemData item, int amount, ref bool __result)
		{
			//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_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_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_009a: 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_00b4: 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_00be: Unknown result type (might be due to invalid IL or missing references)
			FeastInfo feastInfo = InfoOf(item);
			if (feastInfo == null || !_dropAsFeast.Value)
			{
				return true;
			}
			__result = false;
			if (!Ground(((Component)__instance).transform.position + ((Component)__instance).transform.forward * 1.2f, out var point))
			{
				((Character)__instance).Message((MessageType)2, "$msg_cantdrop", 0, (Sprite)null, false);
				return false;
			}
			if (inventory == null)
			{
				inventory = __instance.GetInventory();
			}
			if (amount <= 0 || amount > item.m_stack)
			{
				amount = item.m_stack;
			}
			if (!inventory.RemoveItem(item, amount))
			{
				return false;
			}
			Quaternion rotation = ((Component)__instance).transform.rotation;
			Quaternion rot = Quaternion.Euler(0f, ((Quaternion)(ref rotation)).eulerAngles.y + 180f, 0f);
			SetOut(feastInfo, amount * Cost(), point, rot);
			__result = true;
			return false;
		}
	}

	[HarmonyPatch(typeof(ItemDrop), "DropItem")]
	private static class ItemDrop_DropItem_Patch
	{
		private static bool Prefix(ItemData item, int amount, Vector3 position, Quaternion rotation, ref ItemDrop __result)
		{
			//IL_002d: 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_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: 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)
			FeastInfo feastInfo = InfoOf(item);
			if (feastInfo == null || !_dropAsFeast.Value)
			{
				return true;
			}
			if (amount <= 0 || amount > item.m_stack)
			{
				amount = item.m_stack;
			}
			if (!Ground(position, out var point))
			{
				point = position;
			}
			SetOut(feastInfo, amount * Cost(), point, Quaternion.Euler(0f, ((Quaternion)(ref rotation)).eulerAngles.y, 0f));
			__result = null;
			return false;
		}
	}

	[HarmonyPatch(typeof(Player), "RemovePiece")]
	private static class Player_RemovePiece_Patch
	{
		private static void Prefix()
		{
			_removing = true;
		}

		private static Exception Finalizer(Exception __exception)
		{
			_removing = false;
			return __exception;
		}
	}

	[HarmonyPatch(typeof(WearNTear), "Remove")]
	private static class WearNTear_Remove_Patch
	{
		private static void Prefix(WearNTear __instance)
		{
			if (!_removing || !_leftovers.Value)
			{
				return;
			}
			Feast component = ((Component)__instance).GetComponent<Feast>();
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)component == (Object)null || (Object)(object)localPlayer == (Object)null)
			{
				return;
			}
			FeastInfo feastInfo = InfoOf(component);
			if (feastInfo == null)
			{
				return;
			}
			int num = PortionsLeft(component);
			if (num > 0 && num < component.m_eatStacks)
			{
				int num2 = ((num / Cost() > 0) ? Give(localPlayer, feastInfo, num / Cost()) : 0);
				if (num2 > 0)
				{
					((Character)localPlayer).Message((MessageType)1, "$msg_added " + feastInfo.Shared.m_name, num2, feastInfo.Shared.m_icons[0], false);
				}
			}
		}
	}

	public const string Guid = "j1ga.feastportions";

	public const string Name = "FeastPortions";

	public const string Version = "0.1.1";

	private static ConfigEntry<bool> _takePortions;

	private static ConfigEntry<bool> _leftovers;

	private static ConfigEntry<bool> _removeEmpty;

	private static ConfigEntry<bool> _keepOut;

	private static ConfigEntry<bool> _dropAsFeast;

	private static ConfigEntry<float> _minutes;

	private static ConfigEntry<int> _cost;

	private static readonly Dictionary<string, FeastInfo> _byPiece = new Dictionary<string, FeastInfo>(StringComparer.Ordinal);

	private static readonly Dictionary<string, FeastInfo> _byFood = new Dictionary<string, FeastInfo>(StringComparer.Ordinal);

	private static readonly Dictionary<string, FeastInfo> _byPortion = new Dictionary<string, FeastInfo>(StringComparer.Ordinal);

	private static readonly Dictionary<ZDOID, Bite> _bites = new Dictionary<ZDOID, Bite>();

	private static GameObject _root;

	private static bool _removing;

	private Harmony _harmony;

	private static readonly MethodInfo _memberwiseClone = typeof(object).GetMethod("MemberwiseClone", BindingFlags.Instance | BindingFlags.NonPublic);

	private static readonly FieldInfo _namedPrefabs = AccessTools.Field(typeof(ZNetScene), "m_namedPrefabs");

	private static readonly Dictionary<Inventory, Container> _containers = new Dictionary<Inventory, Container>();

	private static float _keepOutMessage;

	private void Awake()
	{
		//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cd: Expected O, but got Unknown
		//IL_0101: Unknown result type (might be due to invalid IL or missing references)
		//IL_010b: Expected O, but got Unknown
		//IL_013d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0147: Expected O, but got Unknown
		_takePortions = ((BaseUnityPlugin)this).Config.Bind<bool>("01 General", "TakePortions", true, "Shift + E (alt use) on a placed feast puts one portion into the inventory instead of eating it.");
		_leftovers = ((BaseUnityPlugin)this).Config.Bind<bool>("01 General", "LeftoversOnRemove", true, "Taking up a started feast with the serving tray gives the portions left (the game gives nothing). A whole feast still comes back whole.");
		_dropAsFeast = ((BaseUnityPlugin)this).Config.Bind<bool>("01 General", "DropAsFeast", true, "Dropped portions are set out as a feast again, with the servings they took. Off: they drop as ordinary items.");
		_keepOut = ((BaseUnityPlugin)this).Config.Bind<bool>("01 General", "KeepOutOfChests", true, "Portions cannot be put into chests, carts or ship storage (a tombstone still takes them). A player without the mod does not see a portion in a chest, and once they move anything in it the chest is saved without it. Off: for groups where everyone has the mod.");
		_removeEmpty = ((BaseUnityPlugin)this).Config.Bind<bool>("01 General", "RemoveEmptyFeast", true, "The empty serving tray disappears once you take or eat the last portion (the game leaves it standing).");
		_cost = ((BaseUnityPlugin)this).Config.Bind<int>("02 Portions", "Cost", 2, new ConfigDescription("Servings of the feast one carried portion takes. Eating at the table always takes one.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 5), new object[0]));
		_minutes = ((BaseUnityPlugin)this).Config.Bind<float>("02 Portions", "Duration", 30f, new ConfigDescription("How long a portion lasts once eaten, in minutes. A feast eaten at the table lasts 50.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 120f), new object[0]));
		_minutes.SettingChanged += delegate
		{
			foreach (FeastInfo value in _byPiece.Values)
			{
				Dress(value);
			}
		};
		_harmony = new Harmony("j1ga.feastportions");
		Type[] nestedTypes = typeof(FeastPortionsPlugin).GetNestedTypes(BindingFlags.NonPublic);
		foreach (Type type in nestedTypes)
		{
			if (type.GetCustomAttributes(typeof(HarmonyPatch), inherit: false).Length != 0)
			{
				try
				{
					_harmony.CreateClassProcessor(type).Patch();
				}
				catch (Exception ex)
				{
					((BaseUnityPlugin)this).Logger.LogError((object)("Patch " + type.Name + " failed: " + ex.Message));
				}
			}
		}
		((BaseUnityPlugin)this).Logger.LogInfo((object)"FeastPortions 0.1.1 loaded.");
	}

	private void OnDestroy()
	{
		if (_harmony != null)
		{
			_harmony.UnpatchSelf();
		}
	}

	private static bool Russian()
	{
		if (Localization.instance != null)
		{
			return Localization.instance.GetSelectedLanguage() == "Russian";
		}
		return false;
	}

	private static string T(string en, string ru)
	{
		if (!Russian())
		{
			return en;
		}
		return ru;
	}

	private static Transform Root()
	{
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Expected O, but got Unknown
		if ((Object)(object)_root == (Object)null)
		{
			_root = new GameObject("FeastPortions_Prefabs");
			_root.SetActive(false);
			Object.DontDestroyOnLoad((Object)(object)_root);
		}
		return _root.transform;
	}

	private static FeastInfo Learn(GameObject piece)
	{
		//IL_0138: Unknown result type (might be due to invalid IL or missing references)
		//IL_013f: Expected O, but got Unknown
		if ((Object)(object)piece == (Object)null)
		{
			return null;
		}
		if (_byPiece.TryGetValue(((Object)piece).name, out var value))
		{
			return value;
		}
		Feast component = piece.GetComponent<Feast>();
		if ((Object)(object)component == (Object)null)
		{
			return null;
		}
		ItemDrop val = (((Object)(object)component.m_foodItem != (Object)null) ? component.m_foodItem : piece.GetComponent<ItemDrop>());
		if ((Object)(object)val == (Object)null || val.m_itemData == null || val.m_itemData.m_shared == null || val.m_itemData.m_shared.m_food <= 0f)
		{
			return null;
		}
		Piece component2 = piece.GetComponent<Piece>();
		ItemDrop val2 = null;
		if ((Object)(object)component2 != (Object)null && component2.m_resources != null)
		{
			Requirement[] resources = component2.m_resources;
			foreach (Requirement val3 in resources)
			{
				if (val3 != null && (Object)(object)val3.m_resItem != (Object)null)
				{
					val2 = val3.m_resItem;
					break;
				}
			}
		}
		if ((Object)(object)val2 == (Object)null)
		{
			return null;
		}
		GameObject val4 = Object.Instantiate<GameObject>(((Component)val2).gameObject, Root(), false);
		((Object)val4).name = ((Object)piece).name + "_Portion";
		ItemDrop component3 = val4.GetComponent<ItemDrop>();
		SharedData val5 = (SharedData)_memberwiseClone.Invoke(val.m_itemData.m_shared, null);
		component3.m_itemData.m_shared = val5;
		component3.m_itemData.m_stack = 1;
		component3.m_itemData.m_dropPrefab = val4;
		value = new FeastInfo();
		value.Piece = piece;
		value.Food = val;
		value.Portions = Math.Max(1, component.m_eatStacks);
		value.Portion = val4;
		value.Shared = val5;
		if (val5.m_icons != null && val5.m_icons.Length > 0 && (Object)(object)val5.m_icons[0] != (Object)null)
		{
			val5.m_icons = (Sprite[])(object)new Sprite[1] { SliceIcon(val5.m_icons[0]) };
		}
		Dress(value);
		_byPiece[((Object)piece).name] = value;
		_byFood[((Object)((Component)val).gameObject).name] = value;
		_byPortion[((Object)val4).name] = value;
		return value;
	}

	private static void Dress(FeastInfo info)
	{
		SharedData shared = info.Food.m_itemData.m_shared;
		string text = ((Localization.instance != null) ? Localization.instance.Localize(shared.m_name) : shared.m_name);
		string text2 = ((Localization.instance != null) ? Localization.instance.Localize(shared.m_description) : shared.m_description);
		info.Shared.m_name = T(text + " portion", "Кусочек: " + text);
		info.Shared.m_description = T("One portion of a feast, to eat on the road.", "Кусочек пира, чтобы съесть в пути.") + "\n\n" + text2;
		info.Shared.m_maxStackSize = info.Portions;
		info.Shared.m_foodBurnTime = Mathf.Max(1f, _minutes.Value) * 60f;
	}

	private static Sprite SliceIcon(Sprite src)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_0058: Unknown result type (might be due to invalid IL or missing references)
		//IL_005f: Expected O, but got Unknown
		//IL_0075: Unknown result type (might be due to invalid IL or missing references)
		//IL_018d: Unknown result type (might be due to invalid IL or missing references)
		//IL_019c: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ff: 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_0131: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			Rect textureRect = src.textureRect;
			Texture texture = (Texture)(object)src.texture;
			RenderTexture temporary = RenderTexture.GetTemporary(texture.width, texture.height, 0, (RenderTextureFormat)0, (RenderTextureReadWrite)2);
			Graphics.Blit(texture, temporary);
			RenderTexture active = RenderTexture.active;
			RenderTexture.active = temporary;
			int num = Mathf.RoundToInt(((Rect)(ref textureRect)).width);
			int num2 = Mathf.RoundToInt(((Rect)(ref textureRect)).height);
			Texture2D val = new Texture2D(num, num2, (TextureFormat)4, false);
			val.ReadPixels(new Rect(((Rect)(ref textureRect)).x, ((Rect)(ref textureRect)).y, (float)num, (float)num2), 0, 0);
			val.Apply();
			RenderTexture.active = active;
			RenderTexture.ReleaseTemporary(temporary);
			Color[] pixels = val.GetPixels();
			float num3 = (float)num * 0.5f;
			float num4 = (float)num2 * 0.5f;
			for (int i = 0; i < num2; i++)
			{
				for (int j = 0; j < num; j++)
				{
					float num5 = Mathf.Atan2((float)i - num4, (float)j - num3) * 57.29578f;
					if (!(num5 >= -75f) || !(num5 <= 15f))
					{
						Color val2 = pixels[i * num + j];
						float grayscale = ((Color)(ref val2)).grayscale;
						ref Color reference = ref pixels[i * num + j];
						reference = new Color(grayscale, grayscale, grayscale, val2.a * 0.3f);
					}
				}
			}
			val.SetPixels(pixels);
			val.Apply();
			((Object)val).name = ((Object)src).name + "_portion";
			return Sprite.Create(val, new Rect(0f, 0f, (float)num, (float)num2), new Vector2(0.5f, 0.5f), src.pixelsPerUnit);
		}
		catch (Exception ex)
		{
			Debug.LogWarning((object)("[FeastPortions] portion icon kept as the feast's: " + ex.Message));
			return src;
		}
	}

	private static void Register(ObjectDB db)
	{
		if ((Object)(object)db == (Object)null || db.m_items == null)
		{
			return;
		}
		GameObject[] array = db.m_items.ToArray();
		foreach (GameObject val in array)
		{
			if ((Object)(object)val == (Object)null)
			{
				continue;
			}
			ItemDrop component = val.GetComponent<ItemDrop>();
			if ((Object)(object)component == (Object)null || component.m_itemData == null || component.m_itemData.m_shared == null)
			{
				continue;
			}
			PieceTable buildPieces = component.m_itemData.m_shared.m_buildPieces;
			if ((Object)(object)buildPieces == (Object)null || buildPieces.m_pieces == null)
			{
				continue;
			}
			foreach (GameObject piece in buildPieces.m_pieces)
			{
				Learn(piece);
			}
		}
		bool flag = false;
		foreach (FeastInfo value in _byPiece.Values)
		{
			Dress(value);
			if (!db.m_items.Contains(value.Portion))
			{
				db.m_items.Add(value.Portion);
				flag = true;
			}
		}
		if (flag)
		{
			AccessTools.Method(typeof(ObjectDB), "UpdateRegisters", (Type[])null, (Type[])null).Invoke(db, null);
		}
	}

	private static void Register(ZNetScene scene)
	{
		if ((Object)(object)scene == (Object)null || scene.m_prefabs == null)
		{
			return;
		}
		GameObject[] array = scene.m_prefabs.ToArray();
		foreach (GameObject val in array)
		{
			if ((Object)(object)val != (Object)null && (Object)(object)val.GetComponent<Feast>() != (Object)null)
			{
				Learn(val);
			}
		}
		Dictionary<int, GameObject> dictionary = _namedPrefabs.GetValue(scene) as Dictionary<int, GameObject>;
		foreach (FeastInfo value in _byPiece.Values)
		{
			if (!scene.m_prefabs.Contains(value.Portion))
			{
				scene.m_prefabs.Add(value.Portion);
			}
			if (dictionary != null)
			{
				dictionary[StringExtensionMethods.GetStableHashCode(((Object)value.Portion).name)] = value.Portion;
			}
		}
	}

	private static FeastInfo InfoOf(Feast feast)
	{
		if (!_byPiece.TryGetValue(Utils.GetPrefabName(((Component)feast).gameObject), out var value))
		{
			return Learn(((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab(Utils.GetPrefabName(((Component)feast).gameObject)) : null);
		}
		return value;
	}

	private static int PortionsLeft(Feast feast)
	{
		ZNetView component = ((Component)feast).GetComponent<ZNetView>();
		if ((Object)(object)component == (Object)null || !component.IsValid())
		{
			return feast.m_eatStacks;
		}
		return component.GetZDO().GetInt(ZDOVars.s_value, feast.m_eatStacks);
	}

	private static int Give(Player player, FeastInfo info, int count)
	{
		//IL_0070: 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_0080: Unknown result type (might be due to invalid IL or missing references)
		//IL_0085: 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_0095: Unknown result type (might be due to invalid IL or missing references)
		Inventory inventory = ((Humanoid)player).GetInventory();
		int i;
		for (i = 0; i < count; i++)
		{
			if (inventory.AddItem(((Object)info.Portion).name, 1, 1, 0, 0L, "", false, true) == null)
			{
				break;
			}
		}
		if (i < count)
		{
			ItemData val = info.Portion.GetComponent<ItemDrop>().m_itemData.Clone();
			val.m_dropPrefab = info.Portion;
			val.m_stack = count - i;
			Transform transform = ((Component)player).transform;
			ItemDrop.DropItem(val, val.m_stack, transform.position + transform.forward * 0.7f + Vector3.up, transform.rotation);
			((Character)player).Message((MessageType)2, "$inventory_full", 0, (Sprite)null, false);
		}
		return i;
	}

	private static FeastInfo InfoOf(ItemData item)
	{
		if (item == null || (Object)(object)item.m_dropPrefab == (Object)null)
		{
			return null;
		}
		if (!_byPortion.TryGetValue(((Object)item.m_dropPrefab).name, out var value))
		{
			return null;
		}
		return value;
	}

	private static int Cost()
	{
		return Mathf.Clamp(_cost.Value, 1, 5);
	}

	private static void SetOut(FeastInfo info, int servings, Vector3 pos, Quaternion rot)
	{
		//IL_001a: 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_004c: 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)
		//IL_005d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0062: Unknown result type (might be due to invalid IL or missing references)
		//IL_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)
		while (servings > 0)
		{
			int num = Math.Min(servings, info.Portions);
			servings -= num;
			GameObject val = Object.Instantiate<GameObject>(info.Piece, pos, rot);
			ZNetView component = val.GetComponent<ZNetView>();
			if ((Object)(object)component != (Object)null && component.IsValid())
			{
				component.GetZDO().Set(ZDOVars.s_value, num, false);
			}
			pos += rot * new Vector3(0.6f, 0f, 0f);
		}
	}

	private static bool Ground(Vector3 from, out Vector3 point)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0002: 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_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)
		//IL_0055: Unknown result type (might be due to invalid IL or missing references)
		//IL_005a: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_007f: Unknown result type (might be due to invalid IL or missing references)
		point = from;
		int mask = LayerMask.GetMask(new string[6] { "Default", "static_solid", "Default_small", "piece", "terrain", "vehicle" });
		RaycastHit val = default(RaycastHit);
		if (!Physics.Raycast(from + Vector3.up * 1.5f, Vector3.down, ref val, 6f, mask))
		{
			return false;
		}
		if ((Object)(object)ZoneSystem.instance != (Object)null && ((RaycastHit)(ref val)).point.y < ZoneSystem.instance.m_waterLevel - 0.3f)
		{
			return false;
		}
		point = ((RaycastHit)(ref val)).point;
		return true;
	}

	private static void RemoveEmpty(Feast feast)
	{
		if (_removeEmpty.Value && !((Object)(object)feast == (Object)null))
		{
			WearNTear component = ((Component)feast).GetComponent<WearNTear>();
			if ((Object)(object)component != (Object)null)
			{
				component.Remove(true);
			}
		}
	}

	private static bool KeptOut(Inventory inv, ItemData item)
	{
		if (!_keepOut.Value || inv == null || InfoOf(item) == null)
		{
			return false;
		}
		if (!_containers.TryGetValue(inv, out var value))
		{
			return false;
		}
		if ((Object)(object)value == (Object)null)
		{
			_containers.Remove(inv);
			return false;
		}
		if ((Object)(object)((Component)value).GetComponent<TombStone>() != (Object)null)
		{
			return false;
		}
		if ((Object)(object)Player.m_localPlayer != (Object)null && Time.time - _keepOutMessage > 1f)
		{
			_keepOutMessage = Time.time;
			((Character)Player.m_localPlayer).Message((MessageType)2, T("Feast portions stay with you: players without the mod would lose them in a chest", "Кусочки пира не кладутся в сундуки: у игроков без мода они бы пропали"), 0, (Sprite)null, false);
		}
		return true;
	}
}