Decompiled source of Meat Crimes v0.1.6

plugins/MeatCrimes/MeatCrimes.dll

Decompiled a month ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("MeatCrimes")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.1.6.0")]
[assembly: AssemblyInformationalVersion("0.1.6")]
[assembly: AssemblyProduct("MeatCrimes")]
[assembly: AssemblyTitle("MeatCrimes")]
[assembly: AssemblyVersion("0.1.6.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace MeatCrimes
{
	internal static class Content
	{
		internal const string Meat = "MYM_Meat";

		internal const string Peas = "MYM_RestInPeas";

		internal const string Potluck = "MYM_CommunityPotluck";

		internal const string Supper = "MYM_LastSupper";

		internal const string MeatToken = "$mym_meat";

		internal const int DeathYield = 2;

		internal static readonly Dish[] Dishes = new Dish[3]
		{
			new Dish("MYM_RestInPeas", "TurnipStew", "$mym_peas", "$mym_peas_desc", 1, 1, 75f, 28f, 3f, new Ingredient("MYM_Meat", 1), new Ingredient("Carrot", 2), new Ingredient("Mushroom", 1)),
			new Dish("MYM_CommunityPotluck", "SerpentStew", "$mym_potluck", "$mym_potluck_desc", 2, 3, 90f, 90f, 5f, new Ingredient("MYM_Meat", 2), new Ingredient("RawMeat", 2), new Ingredient("Turnip", 2), new Ingredient("Onion", 2)),
			new Dish("MYM_LastSupper", "PiquantPie", "$mym_supper", "$mym_supper_desc", 2, 3, 120f, 120f, 8f, new Ingredient("MYM_Meat", 4), new Ingredient("OatFlour", 2), new Ingredient("Lingonberry", 2), new Ingredient("Sap", 2))
			{
				Duration = 2400f
			}
		};

		internal static readonly Dictionary<string, string> English = new Dictionary<string, string>
		{
			["mym_meat"] = "Meat",
			["mym_meat_desc"] = "Once, you knew this by another name.",
			["mym_peas"] = "Rest in Peas",
			["mym_peas_desc"] = "You saved them a place. Close to the fire.",
			["mym_potluck"] = "Community Potluck",
			["mym_potluck_desc"] = "There is enough of everyone to go around.",
			["mym_regret"] = "Brief Regret",
			["mym_regret_message"] = "Your hunger has quieted. So has something human within you.",
			["mym_voice_message"] = "You hear a familiar voice.",
			["mym_supper"] = "The Last Supper",
			["mym_supper_desc"] = "No one left the table. Nothing remained upon it.",
			["mym_flies_message"] = "Something has mistaken you for what you ate."
		};

		internal static bool IsDish(string prefab)
		{
			if (!(prefab == "MYM_RestInPeas") && !(prefab == "MYM_CommunityPotluck"))
			{
				return prefab == "MYM_LastSupper";
			}
			return true;
		}
	}
	internal sealed class Dish
	{
		internal readonly string Prefab;

		internal readonly string BasePrefab;

		internal readonly string Name;

		internal readonly string Description;

		internal readonly int Yield;

		internal readonly int StationLevel;

		internal readonly float Health;

		internal readonly float Stamina;

		internal readonly float Regen;

		internal float Duration = 1800f;

		internal readonly Ingredient[] Ingredients;

		internal Dish(string prefab, string basePrefab, string name, string description, int yield, int stationLevel, float health, float stamina, float regen, params Ingredient[] ingredients)
		{
			Prefab = prefab;
			BasePrefab = basePrefab;
			Name = name;
			Description = description;
			Yield = yield;
			StationLevel = stationLevel;
			Health = health;
			Stamina = stamina;
			Regen = regen;
			Ingredients = ingredients;
		}
	}
	internal readonly struct Ingredient
	{
		internal readonly string Prefab;

		internal readonly int Amount;

		internal Ingredient(string prefab, int amount)
		{
			Prefab = prefab;
			Amount = amount;
		}
	}
	internal static class Diagnostics
	{
		internal static IEnumerable<string> Run()
		{
			yield return "Meat Crimes 0.1.6 diagnostics (read-only)";
			yield return $"Rest in Peas effect: {6f}s (vanilla main stream starts at ~2s). Messages: screen center.";
			if (!Object.op_Implicit((Object)(object)ObjectDB.instance) || !Object.op_Implicit((Object)(object)ZNetScene.instance))
			{
				yield return "Enter a world before running meatcrimes_check.";
				yield break;
			}
			string[] array = new string[4] { "MYM_Meat", "MYM_RestInPeas", "MYM_CommunityPotluck", "MYM_LastSupper" };
			foreach (string id in array)
			{
				GameObject obj = ObjectDB.instance.GetItemPrefab(id);
				ItemDrop val = (Object.op_Implicit((Object)(object)obj) ? obj.GetComponent<ItemDrop>() : null);
				if (!Object.op_Implicit((Object)(object)val))
				{
					yield return "FAIL: missing item " + id;
					continue;
				}
				SharedData shared = val.m_itemData.m_shared;
				yield return (Object.op_Implicit((Object)(object)ZNetScene.instance.GetPrefab(id)) ? "PASS" : "FAIL") + ": network prefab " + id;
				yield return $"{id}: {shared.m_food} HP / {shared.m_foodStamina} stamina / {shared.m_foodRegen} HP per tick / {shared.m_foodBurnTime}s; stack {shared.m_maxStackSize}";
				yield return ((shared.m_icons != null && shared.m_icons.Length != 0 && Object.op_Implicit((Object)(object)shared.m_icons[0])) ? "PASS" : "FAIL") + ": " + id + " inventory icon";
				if (id == "MYM_Meat")
				{
					yield return (Object.op_Implicit((Object)(object)obj.GetComponent<Floating>()) ? "PASS" : "FAIL") + ": Meat floating component";
				}
			}
			Dish[] dishes = Content.Dishes;
			foreach (Dish dish in dishes)
			{
				Recipe recipe = ((IEnumerable<Recipe>)ObjectDB.instance.m_recipes).FirstOrDefault((Func<Recipe, bool>)((Recipe r) => Object.op_Implicit((Object)(object)r.m_item) && ((Object)((Component)r.m_item).gameObject).name == dish.Prefab));
				yield return ((Object.op_Implicit((Object)(object)recipe) && Object.op_Implicit((Object)(object)recipe.m_craftingStation) && recipe.m_minStationLevel == dish.StationLevel && recipe.m_amount == dish.Yield && recipe.m_resources.Length == dish.Ingredients.Length && dish.Ingredients.All((Ingredient ingredient) => recipe.m_resources.Any((Requirement r) => Object.op_Implicit((Object)(object)r.m_resItem) && ((Object)((Component)r.m_resItem).gameObject).name == ingredient.Prefab && r.m_amount == ingredient.Amount))) ? "PASS" : "FAIL") + ": recipe " + dish.Prefab;
			}
			GameObject itemPrefab = ObjectDB.instance.GetItemPrefab("Pukeberries");
			StatusEffect val2 = (Object.op_Implicit((Object)(object)itemPrefab) ? itemPrefab.GetComponent<ItemDrop>().m_itemData.m_shared.m_consumeStatusEffect : null);
			yield return ((Object.op_Implicit((Object)(object)val2) && val2.m_startEffects.HasEffects()) ? "PASS" : "FAIL") + ": vanilla vomiting effects";
			GameObject prefab = PrefabManager.Instance.GetPrefab("sfx_ghost_idle");
			yield return ((Object.op_Implicit((Object)(object)prefab) && Object.op_Implicit((Object)(object)prefab.GetComponent<ZNetView>())) ? "PASS" : "FAIL") + ": networked ghost sound";
			GameObject prefab2 = PrefabManager.Instance.GetPrefab("Flies");
			ParticleSystem val3 = (Object.op_Implicit((Object)(object)prefab2) ? prefab2.GetComponentInChildren<ParticleSystem>(true) : null);
			yield return string.Format("{0}: local flies particles ({1}s)", (Object.op_Implicit((Object)(object)val3) && !Object.op_Implicit((Object)(object)((Component)val3).GetComponentInChildren<ZNetView>(true))) ? "PASS" : "FAIL", 6f);
			GameObject prefab3 = PrefabManager.Instance.GetPrefab("piece_beehive");
			yield return ((Object.op_Implicit((Object)(object)prefab3) && prefab3.GetComponentsInChildren<ZSFX>(true).Any((ZSFX sfx) => Object.op_Implicit((Object)(object)((Component)sfx).GetComponent<AudioSource>()) && sfx.m_audioClips != null && sfx.m_audioClips.Any((AudioClip clip) => Object.op_Implicit((Object)(object)clip) && ((Object)clip).name == "Insect_FlySwarmLoop1"))) ? "PASS" : "FAIL") + ": beehive fly buzzing clip and audio source";
			yield return "Next: death, recipe discovery, eating, water and multiplayer checks in TESTING.md.";
			yield return "Cosmetic previews: meatcrimes_puke / meatcrimes_ghost / meatcrimes_flies. None change food buffs.";
		}
	}
	internal static class MeatArt
	{
		internal static void Lighten(GameObject prefab)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			Tint(prefab, new Color(1f, 0.79f, 0.77f), 0.32f);
		}

		internal static void Darken(GameObject prefab)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			Tint(prefab, new Color(0.16f, 0.06f, 0.04f), 0.25f);
		}

		private static void Tint(GameObject prefab, Color tint, float strength)
		{
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Expected O, but got Unknown
			//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)
			Dictionary<Texture, Texture2D> dictionary = new Dictionary<Texture, Texture2D>();
			Renderer[] componentsInChildren = prefab.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val in componentsInChildren)
			{
				if (!(val is MeshRenderer) && !(val is SkinnedMeshRenderer))
				{
					continue;
				}
				Material[] sharedMaterials = val.sharedMaterials;
				for (int j = 0; j < sharedMaterials.Length; j++)
				{
					if (!Object.op_Implicit((Object)(object)sharedMaterials[j]))
					{
						continue;
					}
					Material val2 = new Material(sharedMaterials[j]);
					((Object)val2).name = "MYM_Pale_" + ((Object)sharedMaterials[j]).name;
					Texture mainTexture = val2.mainTexture;
					if (Object.op_Implicit((Object)(object)mainTexture))
					{
						if (!dictionary.TryGetValue(mainTexture, out var value))
						{
							value = (dictionary[mainTexture] = ReadAndTint(mainTexture, new Rect(0f, 0f, (float)mainTexture.width, (float)mainTexture.height), tint, strength));
						}
						val2.mainTexture = (Texture)(object)value;
					}
					sharedMaterials[j] = val2;
				}
				val.sharedMaterials = sharedMaterials;
			}
			SharedData shared = prefab.GetComponent<ItemDrop>().m_itemData.m_shared;
			Sprite[] array = (Sprite[])shared.m_icons.Clone();
			for (int k = 0; k < array.Length; k++)
			{
				Sprite val4 = array[k];
				if (Object.op_Implicit((Object)(object)val4))
				{
					Texture2D val5 = ReadAndTint((Texture)(object)val4.texture, val4.textureRect, tint, strength);
					array[k] = Sprite.Create(val5, new Rect(0f, 0f, (float)((Texture)val5).width, (float)((Texture)val5).height), new Vector2(0.5f, 0.5f));
					((Object)array[k]).name = "MYM_" + ((Object)prefab).name + "_Icon";
				}
			}
			shared.m_icons = array;
		}

		private static Texture2D ReadAndTint(Texture source, Rect rect, Color tint, float strength)
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			RenderTexture active = RenderTexture.active;
			RenderTexture temporary = RenderTexture.GetTemporary(source.width, source.height, 0, (RenderTextureFormat)0);
			try
			{
				Graphics.Blit(source, temporary);
				RenderTexture.active = temporary;
				Texture2D val = new Texture2D((int)((Rect)(ref rect)).width, (int)((Rect)(ref rect)).height, (TextureFormat)4, false);
				val.ReadPixels(rect, 0, 0);
				Color[] pixels = val.GetPixels();
				for (int i = 0; i < pixels.Length; i++)
				{
					Color val2 = pixels[i];
					Color val3 = Color.Lerp(val2, tint, strength);
					val3.a = val2.a;
					pixels[i] = val3;
				}
				val.SetPixels(pixels);
				val.Apply();
				((Object)val).name = "MYM_PaleMeat_" + ((Object)source).name;
				((Texture)val).wrapMode = source.wrapMode;
				((Texture)val).filterMode = source.filterMode;
				return val;
			}
			finally
			{
				RenderTexture.active = active;
				RenderTexture.ReleaseTemporary(temporary);
			}
		}
	}
	[BepInPlugin("bobk.meatcrimes", "Meat Crimes", "0.1.6")]
	[BepInDependency("com.jotunn.jotunn", "2.30.0")]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	public sealed class Plugin : BaseUnityPlugin
	{
		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static ConsoleEvent <>9__15_0;

			public static Func<Ingredient, RequirementConfig> <>9__16_0;

			public static Func<AudioClip, bool> <>9__26_1;

			public static Func<ZSFX, bool> <>9__26_0;

			public static Func<AudioClip, bool> <>9__27_0;

			internal void <Awake>b__15_0(ConsoleEventArgs args)
			{
				foreach (string item in Diagnostics.Run())
				{
					args.Context.AddString(item);
				}
			}

			internal RequirementConfig <RegisterContent>b__16_0(Ingredient i)
			{
				//IL_000e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0014: Expected O, but got Unknown
				return new RequirementConfig(i.Prefab, i.Amount, 0, true);
			}

			internal bool <FindFliesBuzz>b__26_0(ZSFX sfx)
			{
				if (sfx.m_audioClips != null)
				{
					return sfx.m_audioClips.Any((AudioClip clip) => Object.op_Implicit((Object)(object)clip) && ((Object)clip).name == "Insect_FlySwarmLoop1");
				}
				return false;
			}

			internal bool <FindFliesBuzz>b__26_1(AudioClip clip)
			{
				if (Object.op_Implicit((Object)(object)clip))
				{
					return ((Object)clip).name == "Insect_FlySwarmLoop1";
				}
				return false;
			}

			internal bool <PlayFliesBuzz>b__27_0(AudioClip clip)
			{
				if (Object.op_Implicit((Object)(object)clip))
				{
					return ((Object)clip).name == "Insect_FlySwarmLoop1";
				}
				return false;
			}
		}

		public const string Guid = "bobk.meatcrimes";

		public const string ModName = "Meat Crimes";

		public const string ModVersion = "0.1.6";

		internal const float RegretDuration = 6f;

		internal const float FliesDuration = 6f;

		internal static Plugin Instance;

		private Harmony harmony;

		private ConfigEntry<bool> cosmeticEffects;

		private StatusEffect regret;

		private GameObject ghostSound;

		private ParticleSystem fliesParticles;

		private GameObject activeFlies;

		private bool registered;

		private bool effectsResolved;

		private bool warnedDrop;

		private void Awake()
		{
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Expected O, but got Unknown
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Expected O, but got Unknown
			//IL_00e8: 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_0113: Expected O, but got Unknown
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Expected O, but got Unknown
			//IL_0134: 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_00b8: Expected O, but got Unknown
			Instance = this;
			cosmeticEffects = ((BaseUnityPlugin)this).Config.Bind<bool>("Cosmetics", "PlayEatingEffects", true, "Trigger vomiting, ghost sound or flies when YOU eat a custom dish. Food stats are unchanged. Client-local setting.");
			CustomLocalization localization = LocalizationManager.Instance.GetLocalization();
			string text = "English";
			localization.AddTranslation(ref text, Content.English);
			PrefabManager.OnVanillaPrefabsAvailable += RegisterContent;
			ItemManager.OnItemsRegistered += ResolveWorldEffects;
			harmony = new Harmony("bobk.meatcrimes");
			harmony.PatchAll(typeof(Plugin).Assembly);
			object obj = <>c.<>9__15_0;
			if (obj == null)
			{
				ConsoleEvent val = delegate(ConsoleEventArgs args)
				{
					foreach (string item in Diagnostics.Run())
					{
						args.Context.AddString(item);
					}
				};
				<>c.<>9__15_0 = val;
				obj = (object)val;
			}
			new ConsoleCommand("meatcrimes_check", "Check Meat Crimes items, recipes and cosmetic assets (read-only).", (ConsoleEvent)obj, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
			new ConsoleCommand("meatcrimes_puke", "Preview the cosmetic vomiting reaction without eating or changing food buffs.", (ConsoleEvent)delegate(ConsoleEventArgs args)
			{
				PreviewReaction(args.Context, "MYM_RestInPeas");
			}, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
			new ConsoleCommand("meatcrimes_ghost", "Preview the Potluck ghost sound and message without eating.", (ConsoleEvent)delegate(ConsoleEventArgs args)
			{
				PreviewReaction(args.Context, "MYM_CommunityPotluck");
			}, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
			new ConsoleCommand("meatcrimes_flies", "Preview The Last Supper flies and message without eating.", (ConsoleEvent)delegate(ConsoleEventArgs args)
			{
				PreviewReaction(args.Context, "MYM_LastSupper");
			}, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Meat Crimes 0.1.6 loaded. Two Meat per death; farming encouraged.");
		}

		private void RegisterContent()
		{
			//IL_019b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ba: 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_01d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01df: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Expected O, but got Unknown
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_022a: Expected O, but got Unknown
			//IL_023a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0241: Expected O, but got Unknown
			//IL_0254: Unknown result type (might be due to invalid IL or missing references)
			if (registered)
			{
				return;
			}
			try
			{
				RequirePrefab("BjornMeat");
				Dish[] dishes = Content.Dishes;
				foreach (Dish obj in dishes)
				{
					RequirePrefab(obj.BasePrefab);
					Ingredient[] ingredients = obj.Ingredients;
					for (int j = 0; j < ingredients.Length; j++)
					{
						Ingredient ingredient = ingredients[j];
						if (ingredient.Prefab != "MYM_Meat")
						{
							RequirePrefab(ingredient.Prefab);
						}
					}
				}
				CustomItem val = new CustomItem("MYM_Meat", "BjornMeat");
				SharedData shared = val.ItemDrop.m_itemData.m_shared;
				shared.m_name = "$mym_meat";
				shared.m_description = "$mym_meat_desc";
				shared.m_itemType = (ItemType)1;
				shared.m_food = (shared.m_foodStamina = (shared.m_foodEitr = (shared.m_foodRegen = (shared.m_foodBurnTime = 0f))));
				shared.m_consumeStatusEffect = null;
				shared.m_maxStackSize = 20;
				shared.m_weight = 1f;
				shared.m_teleportable = true;
				val.ItemDrop.m_itemData.m_dropPrefab = val.ItemPrefab;
				if (!Object.op_Implicit((Object)(object)val.ItemPrefab.GetComponent<Floating>()))
				{
					val.ItemPrefab.AddComponent<Floating>();
				}
				if (!ItemManager.Instance.AddItem(val))
				{
					throw new InvalidOperationException("Meat registration failed.");
				}
				if (!GraphicsUnavailable())
				{
					try
					{
						MeatArt.Lighten(val.ItemPrefab);
					}
					catch (Exception arg)
					{
						((BaseUnityPlugin)this).Logger.LogWarning((object)$"Meat recolor failed; retaining original art: {arg}");
					}
				}
				dishes = Content.Dishes;
				foreach (Dish dish in dishes)
				{
					ItemConfig val2 = new ItemConfig
					{
						Name = dish.Name,
						Description = dish.Description,
						Amount = dish.Yield,
						CraftingStation = "piece_cauldron",
						MinStationLevel = dish.StationLevel,
						StackSize = 20,
						Weight = 1f,
						Requirements = ((IEnumerable<Ingredient>)dish.Ingredients).Select((Func<Ingredient, RequirementConfig>)((Ingredient ingredient2) => new RequirementConfig(ingredient2.Prefab, ingredient2.Amount, 0, true))).ToArray()
					};
					CustomItem val3 = new CustomItem(dish.Prefab, dish.BasePrefab, val2);
					SharedData shared2 = val3.ItemDrop.m_itemData.m_shared;
					shared2.m_itemType = (ItemType)2;
					shared2.m_food = dish.Health;
					shared2.m_foodStamina = dish.Stamina;
					shared2.m_foodEitr = 0f;
					shared2.m_foodRegen = dish.Regen;
					shared2.m_foodBurnTime = dish.Duration;
					shared2.m_consumeStatusEffect = null;
					shared2.m_teleportable = true;
					val3.ItemDrop.m_itemData.m_dropPrefab = val3.ItemPrefab;
					if (!ItemManager.Instance.AddItem(val3))
					{
						throw new InvalidOperationException(dish.Prefab + " registration failed.");
					}
					if (dish.Prefab == "MYM_LastSupper" && !GraphicsUnavailable())
					{
						try
						{
							MeatArt.Darken(val3.ItemPrefab);
						}
						catch (Exception arg2)
						{
							((BaseUnityPlugin)this).Logger.LogWarning((object)$"Supper recolor failed; retaining original art: {arg2}");
						}
					}
				}
				registered = true;
				PrefabManager.OnVanillaPrefabsAvailable -= RegisterContent;
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Registered Meat, Rest in Peas, Community Potluck and The Last Supper with vanilla art.");
			}
			catch (Exception arg3)
			{
				PrefabManager.OnVanillaPrefabsAvailable -= RegisterContent;
				((BaseUnityPlugin)this).Logger.LogError((object)$"Content registration failed. Check game/Jotunn versions: {arg3}");
			}
		}

		internal static GameObject RequirePrefab(string name)
		{
			GameObject prefab = PrefabManager.Instance.GetPrefab(name);
			if (!Object.op_Implicit((Object)(object)prefab))
			{
				throw new InvalidOperationException("Required vanilla prefab not found: " + name);
			}
			return prefab;
		}

		internal static bool GraphicsUnavailable()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Invalid comparison between Unknown and I4
			return (int)SystemInfo.graphicsDeviceType == 4;
		}

		private void ResolveWorldEffects()
		{
			effectsResolved = false;
			fliesParticles = null;
			ResolveEffects();
		}

		private void ResolveEffects()
		{
			if (effectsResolved || GraphicsUnavailable())
			{
				return;
			}
			try
			{
				StatusEffect consumeStatusEffect = RequirePrefab("Pukeberries").GetComponent<ItemDrop>().m_itemData.m_shared.m_consumeStatusEffect;
				if (!Object.op_Implicit((Object)(object)consumeStatusEffect) || !consumeStatusEffect.m_startEffects.HasEffects())
				{
					throw new InvalidOperationException("Bukeperry cosmetic effects missing.");
				}
				regret = ScriptableObject.CreateInstance<StatusEffect>();
				((Object)regret).name = "MYM_BriefRegret";
				regret.m_name = "$mym_regret";
				regret.m_ttl = 6f;
				regret.m_hidden = true;
				regret.m_startEffects = consumeStatusEffect.m_startEffects;
				ghostSound = RequirePrefab("sfx_ghost_idle");
				effectsResolved = true;
				((BaseUnityPlugin)this).Logger.LogInfo((object)$"Cosmetic-only vomiting ({6f}s) and ghost sound ready.");
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Cosmetic assets not ready: " + ex.Message));
			}
		}

		internal void DropMeat(Player player)
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (registered && Object.op_Implicit((Object)(object)ZNetScene.instance))
				{
					GameObject prefab = ZNetScene.instance.GetPrefab("MYM_Meat");
					if (!Object.op_Implicit((Object)(object)prefab))
					{
						throw new InvalidOperationException("Meat is absent from the network prefab registry.");
					}
					ItemData itemData = prefab.GetComponent<ItemDrop>().m_itemData;
					Vector3 val = ((Component)player).transform.position + ((Component)player).transform.right * 0.65f + Vector3.up * 0.5f;
					ItemDrop.DropItem(itemData, 2, val, Quaternion.identity);
				}
			}
			catch (Exception arg)
			{
				if (!warnedDrop)
				{
					((BaseUnityPlugin)this).Logger.LogError((object)$"Could not drop player Meat: {arg}");
					warnedDrop = true;
				}
			}
		}

		internal void OnMeal(Player player, string prefab)
		{
			if (cosmeticEffects.Value && !GraphicsUnavailable())
			{
				((MonoBehaviour)this).StartCoroutine(MealReaction(player, prefab));
			}
		}

		private void PreviewReaction(Terminal terminal, string prefab)
		{
			Player localPlayer = Player.m_localPlayer;
			if (!Object.op_Implicit((Object)(object)localPlayer) || ((Character)localPlayer).IsDead())
			{
				terminal.AddString("Enter a world with a living player first.");
				return;
			}
			if (!cosmeticEffects.Value)
			{
				terminal.AddString("PlayEatingEffects is disabled in the Meat Crimes config.");
				return;
			}
			terminal.AddString("Cosmetic preview queued. Close the console to see it; food buffs are unchanged.");
			OnMeal(localPlayer, prefab);
		}

		private IEnumerator MealReaction(Player player, string prefab)
		{
			yield return (object)new WaitForSeconds(1.5f);
			if (!Object.op_Implicit((Object)(object)player) || (Object)(object)player != (Object)(object)Player.m_localPlayer || ((Character)player).IsDead())
			{
				yield break;
			}
			if (prefab == "MYM_LastSupper")
			{
				PlayFlies(player);
				yield break;
			}
			ResolveEffects();
			if (prefab == "MYM_RestInPeas" && Object.op_Implicit((Object)(object)regret))
			{
				((Character)player).GetSEMan().AddStatusEffect(regret, true, 0, 0f, (short)(-1));
				((Character)player).Message((MessageType)2, "$mym_regret_message", 0, (Sprite)null, false);
				((BaseUnityPlugin)this).Logger.LogInfo((object)$"Started Rest in Peas cosmetic reaction ({6f}s). No food removal or sickness penalties.");
			}
			else if (prefab == "MYM_CommunityPotluck" && Object.op_Implicit((Object)(object)ghostSound))
			{
				Object.Instantiate<GameObject>(ghostSound, ((Character)player).GetCenterPoint(), Quaternion.identity);
				((Character)player).Message((MessageType)2, "$mym_voice_message", 0, (Sprite)null, false);
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Started Community Potluck ghost reaction.");
			}
		}

		private void PlayFlies(Player player)
		{
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			((Character)player).Message((MessageType)2, "$mym_flies_message", 0, (Sprite)null, false);
			try
			{
				if (!Object.op_Implicit((Object)(object)fliesParticles))
				{
					fliesParticles = RequirePrefab("Flies").GetComponentInChildren<ParticleSystem>(true);
				}
				if (!Object.op_Implicit((Object)(object)fliesParticles))
				{
					throw new InvalidOperationException("Flies particle system missing.");
				}
				if (Object.op_Implicit((Object)(object)((Component)fliesParticles).GetComponentInChildren<ZNetView>(true)))
				{
					throw new InvalidOperationException("Unexpected network component on flies particle child.");
				}
				if (Object.op_Implicit((Object)(object)activeFlies))
				{
					Object.Destroy((Object)(object)activeFlies);
				}
				ParticleSystem val = Object.Instantiate<ParticleSystem>(fliesParticles, ((Component)player).transform);
				activeFlies = ((Component)val).gameObject;
				activeFlies.transform.localPosition = Vector3.up * 1.3f;
				activeFlies.transform.localRotation = Quaternion.identity;
				activeFlies.SetActive(true);
				MainModule main = val.main;
				((MainModule)(ref main)).simulationSpace = (ParticleSystemSimulationSpace)0;
				val.Play(true);
				Object.Destroy((Object)(object)activeFlies, 6f);
				PlayFliesBuzz(activeFlies);
				((BaseUnityPlugin)this).Logger.LogInfo((object)$"Started The Last Supper cosmetic flies ({6f}s).");
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not play cosmetic flies: " + ex.Message));
			}
		}

		internal static ZSFX FindFliesBuzz()
		{
			return ((IEnumerable<ZSFX>)RequirePrefab("piece_beehive").GetComponentsInChildren<ZSFX>(true)).FirstOrDefault((Func<ZSFX, bool>)((ZSFX sfx) => sfx.m_audioClips != null && sfx.m_audioClips.Any((AudioClip clip) => Object.op_Implicit((Object)(object)clip) && ((Object)clip).name == "Insect_FlySwarmLoop1")));
		}

		private void PlayFliesBuzz(GameObject swarm)
		{
			try
			{
				ZSFX val = FindFliesBuzz();
				if (!Object.op_Implicit((Object)(object)val))
				{
					throw new InvalidOperationException("Beehive fly buzzing clip missing.");
				}
				AudioSource component = ((Component)val).GetComponent<AudioSource>();
				if (!Object.op_Implicit((Object)(object)component))
				{
					throw new InvalidOperationException("Beehive audio source missing.");
				}
				AudioSource obj = swarm.AddComponent<AudioSource>();
				obj.playOnAwake = false;
				obj.clip = val.m_audioClips.First((AudioClip clip) => Object.op_Implicit((Object)(object)clip) && ((Object)clip).name == "Insect_FlySwarmLoop1");
				obj.outputAudioMixerGroup = component.outputAudioMixerGroup;
				obj.volume = 0.15f;
				obj.spatialBlend = 0f;
				obj.loop = true;
				obj.Play();
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not play flies buzzing: " + ex.Message));
			}
		}

		private void OnDestroy()
		{
			PrefabManager.OnVanillaPrefabsAvailable -= RegisterContent;
			ItemManager.OnItemsRegistered -= ResolveWorldEffects;
			Harmony obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
			((MonoBehaviour)this).StopAllCoroutines();
			if (Object.op_Implicit((Object)(object)activeFlies))
			{
				Object.Destroy((Object)(object)activeFlies);
			}
			if ((Object)(object)Instance == (Object)(object)this)
			{
				Instance = null;
			}
		}
	}
	[HarmonyPatch(typeof(Player), "OnDeath")]
	internal static class DeathPatch
	{
		private static void Prefix(Player __instance, out bool __state)
		{
			ZNetView component = ((Component)__instance).GetComponent<ZNetView>();
			__state = Object.op_Implicit((Object)(object)component) && component.IsValid() && component.IsOwner() && !((Character)__instance).IsDead();
		}

		private static void Postfix(Player __instance, bool __state)
		{
			if (__state && ((Character)__instance).IsDead() && Object.op_Implicit((Object)(object)Plugin.Instance))
			{
				Plugin.Instance.DropMeat(__instance);
			}
		}
	}
	[HarmonyPatch(typeof(Player), "EatFood")]
	internal static class MealPatch
	{
		private static void Postfix(Player __instance, ItemData item, bool __result)
		{
			if (__result && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && Object.op_Implicit((Object)(object)Plugin.Instance))
			{
				string prefab = (Object.op_Implicit((Object)(object)item?.m_dropPrefab) ? ((Object)item.m_dropPrefab).name : null);
				if (Content.IsDish(prefab))
				{
					Plugin.Instance.OnMeal(__instance, prefab);
				}
			}
		}
	}
	[HarmonyPatch(typeof(Player), "HaveRequirements", new Type[]
	{
		typeof(Recipe),
		typeof(bool),
		typeof(int),
		typeof(int)
	})]
	internal static class DiscoveryPatch
	{
		private static void Postfix(Player __instance, Recipe recipe, bool discover, ref bool __result)
		{
			if (discover && Object.op_Implicit((Object)(object)recipe?.m_item) && Content.IsDish(((Object)((Component)recipe.m_item).gameObject).name))
			{
				__result = __instance.IsMaterialKnown("$mym_meat");
			}
		}
	}
}