Decompiled source of ZenBreeding v0.2.4

plugins\ZenBreeding.dll

Decompiled 3 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using JetBrains.Annotations;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using UnityEngine;
using Zen.Config;
using Zen.Lib;
using Zen.Logging;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("ZenBreeding")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ZenBreeding")]
[assembly: AssemblyCopyright("Copyright \ufffd  2021")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")]
[assembly: AssemblyFileVersion("0.2.4")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.2.4.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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 ZenBreeding
{
	[HarmonyPatch]
	public static class Breeding
	{
		internal enum SterilizeType
		{
			None,
			All,
			BabiesOnly
		}

		[HarmonyPatch(typeof(EggGrow), "GrowUpdate")]
		private static class EggGrowUpdate
		{
			[UsedImplicitly]
			private static void Prefix(EggGrow __instance)
			{
				_growerZDO = __instance.m_nview.GetZDO();
			}

			[UsedImplicitly]
			private static void Postfix(EggGrow __instance)
			{
				_growerZDO = null;
			}

			[UsedImplicitly]
			private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> codes)
			{
				return GrowUpdateTranspile(codes);
			}
		}

		[HarmonyPatch(typeof(Growup), "GrowUpdate")]
		private static class GrowUpdate
		{
			[UsedImplicitly]
			private static void Prefix(Growup __instance)
			{
				_growerZDO = __instance.m_nview.GetZDO();
			}

			[UsedImplicitly]
			private static void Postfix(Growup __instance)
			{
				_growerZDO = null;
			}

			[UsedImplicitly]
			private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> codes)
			{
				return GrowUpdateTranspile(codes);
			}
		}

		private static readonly int ZDOVarSterile = StringExtensionMethods.GetStableHashCode("ZenBreeding_Sterile");

		private static readonly int ZDOVarFertile = StringExtensionMethods.GetStableHashCode("ZenBreeding_Fertile");

		private const string SterileEggPrefabName = "ChickenEgg";

		private const string FertileEggPrefabName = "ChickenEggFertile";

		private static ZDO? _growerZDO;

		internal static Action AddEgg()
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Expected O, but got Unknown
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Expected O, but got Unknown
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected O, but got Unknown
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Expected O, but got Unknown
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Expected O, but got Unknown
			Log.Info((object)"Add fertile chicken egg", (ushort)0);
			CustomItem val = new CustomItem("ChickenEggFertile", "ChickenEgg", new ItemConfig
			{
				Name = "$item_chicken_egg_fertile"
			});
			ItemManager.Instance.AddItem(val);
			RecipeConfig val2 = new RecipeConfig();
			val2.Name = "ChickenEgg";
			val2.Item = "ChickenEgg";
			val2.CraftingStation = CraftingStations.FoodPreparationTable;
			val2.Requirements = (RequirementConfig[])(object)new RequirementConfig[1]
			{
				new RequirementConfig("ChickenEggFertile", 1, 0, true)
			};
			RecipeConfig val3 = val2;
			ItemManager.Instance.AddRecipe(new CustomRecipe(val3));
			return ConfigSync;
		}

		private static void ConfigSync()
		{
			if (Configs.Sterilization.Value == SterilizeType.BabiesOnly)
			{
				GameObject itemPrefab = ObjectDB.instance.GetItemPrefab("ChickenEgg");
				SharedData shared = itemPrefab.GetComponent<ItemDrop>().m_itemData.m_shared;
				shared.m_name = "$item_chicken_egg_sterile";
				shared.m_description = "$item_chicken_egg_sterile_description";
			}
		}

		internal static void InitPrefabs()
		{
			if (Configs.Sterilization.Value == SterilizeType.None)
			{
				return;
			}
			EggGrow val = default(EggGrow);
			Trader trader = default(Trader);
			DropTable dropTable = default(DropTable);
			foreach (GameObject prefab in ZNetScene.instance.m_prefabs)
			{
				if (Configs.Sterilization.Value == SterilizeType.All)
				{
					RemoveProcreate(prefab);
				}
				if (Configs.Sterilization.Value == SterilizeType.BabiesOnly && !Configs.BreedingAllowed.Value.Contains(((Object)prefab).name, true))
				{
					if (((Object)prefab).name == "ChickenEgg" && prefab.TryGetComponent<EggGrow>(ref val))
					{
						Object.Destroy((Object)(object)val);
					}
					if (prefab.TryGetComponent<Trader>(ref trader))
					{
						SwapEggTrader(trader);
					}
					Container componentInChildren = prefab.GetComponentInChildren<Container>();
					if (Object.op_Implicit((Object)(object)componentInChildren))
					{
						SwapEggInDropTable(componentInChildren.m_defaultItems);
					}
					if (prefab.TryGetComponent<DropTable>(ref dropTable))
					{
						SwapEggInDropTable(dropTable);
					}
				}
			}
		}

		private static void SwapEggInDropTable(DropTable? dropTable)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: 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_0055: Unknown result type (might be due to invalid IL or missing references)
			if (dropTable == null)
			{
				return;
			}
			GameObject itemPrefab = ObjectDB.instance.GetItemPrefab("ChickenEgg");
			GameObject itemPrefab2 = ObjectDB.instance.GetItemPrefab("ChickenEggFertile");
			List<DropData> drops = dropTable.m_drops;
			if (drops == null)
			{
				return;
			}
			for (int i = 0; i < drops.Count; i++)
			{
				DropData val = drops[i];
				if ((Object)(object)val.m_item == (Object)(object)itemPrefab)
				{
					val.m_item = itemPrefab2;
					drops[i] = val;
				}
			}
		}

		private static void SwapEggTrader(Trader trader)
		{
			if (Configs.Sterilization.Value != SterilizeType.BabiesOnly)
			{
				return;
			}
			Log.Info((object)("Check trader: " + ((Object)trader).name + " for ChickenEgg"), (ushort)0);
			foreach (TradeItem item in trader.m_items)
			{
				ItemDrop prefab = item.m_prefab;
				if (((prefab != null) ? ItemDataExt.GetPrefabName(prefab) : null) == "ChickenEgg")
				{
					GameObject itemPrefab = ObjectDB.instance.GetItemPrefab("ChickenEggFertile");
					ItemDrop val = ((itemPrefab != null) ? itemPrefab.GetComponent<ItemDrop>() : null);
					if (!Object.op_Implicit((Object)(object)val))
					{
						Log.Error((object)"Fertile egg is missing from ObjectDB", (ushort)0);
						break;
					}
					item.m_prefab = val;
					Log.Info((object)"Swapped ChickenEgg for ChickenEggFertile", (ushort)0);
				}
			}
		}

		private static void RemoveProcreate(GameObject prefab)
		{
			Procreation val = default(Procreation);
			if (!Configs.BreedingAllowed.Value.Contains(((Object)prefab).name, true) && prefab.TryGetComponent<Procreation>(ref val))
			{
				Object.Destroy((Object)(object)val);
				Log.Message((object)("Sterilized prefab: " + ((Object)prefab).name), (ushort)0);
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Procreation), "Awake")]
		private static void Procreation_Awake(Procreation __instance)
		{
			if (__instance.m_nview.IsValid() && __instance.m_nview.GetZDO().GetBool(ZDOVarSterile, false))
			{
				Object.Destroy((Object)(object)__instance);
			}
		}

		private static IEnumerable<CodeInstruction> GrowUpdateTranspile(IEnumerable<CodeInstruction> codes)
		{
			MethodInfo methodInfo = AccessTools.FirstMethod(typeof(Object), (Func<MethodInfo, bool>)((MethodInfo info) => info.Name == "Instantiate" && info.IsGenericMethodDefinition && info.GetParameters().Length == 3 && info.GetParameters()[1].ParameterType == typeof(Vector3) && info.GetParameters()[2].ParameterType == typeof(Quaternion))).MakeGenericMethod(typeof(GameObject));
			MethodInfo methodInfo2 = AccessTools.Method(typeof(Breeding), "GrowUpdate_Instantiate_Intercept", (Type[])null, (Type[])null);
			return Transpilers.MethodReplacer(codes, (MethodBase)methodInfo, (MethodBase)methodInfo2);
		}

		private static GameObject GrowUpdate_Instantiate_Intercept(GameObject prefab, Vector3 position, Quaternion rotation)
		{
			//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)
			GameObject val = Object.Instantiate<GameObject>(prefab, position, rotation);
			if (Configs.Sterilization.Value != SterilizeType.BabiesOnly)
			{
				return val;
			}
			if (IsFromFertileEgg())
			{
				Fertilize(val);
			}
			else
			{
				Sterilize(val);
			}
			return val;
		}

		private static bool IsFromFertileEgg()
		{
			if (_growerZDO == null)
			{
				return false;
			}
			if ("ChickenEggFertile" == ZdoExt.GetPrefabName(_growerZDO))
			{
				return true;
			}
			return _growerZDO.GetBool(ZDOVarFertile, false);
		}

		private static void Fertilize(GameObject offspring)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			string name = ((Object)offspring).name;
			ZDO? growerZDO = _growerZDO;
			Log.Info((object)$"Fertilize {name} from {((growerZDO != null) ? ZdoExt.GetPrefabName(growerZDO) : null)} {offspring.transform.position}", (ushort)0);
			ZNetView component = offspring.GetComponent<ZNetView>();
			if (component.IsOwner())
			{
				component.GetZDO().Set(ZDOVarFertile, true);
			}
		}

		private static void Sterilize(GameObject offspring)
		{
			//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)
			string prefabName = Utils.GetPrefabName(((Object)offspring).name);
			Procreation val = default(Procreation);
			if (!Configs.BreedingAllowed.Value.Contains(prefabName, true) && offspring.TryGetComponent<Procreation>(ref val))
			{
				if (val.m_nview.IsOwner())
				{
					val.m_nview.GetZDO().Set(ZDOVarSterile, true);
				}
				Object.Destroy((Object)(object)val);
				Log.Info((object)$"Sterilize {prefabName} {MathExt.XZY(offspring.transform.position)}", (ushort)0);
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Tameable), "GetHoverText")]
		private static void Tameable_GetHoverText(Tameable __instance, ref string __result)
		{
			//IL_004f: 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)
			Procreation val = default(Procreation);
			if (__instance.IsTamed() && ((Component)__instance).TryGetComponent<Procreation>(ref val) && ((Behaviour)val).enabled)
			{
				if (val.IsPregnant())
				{
					__result += StringExt.Localize($"\n<color={UIColor.MajorInfo}>$info_pregnant</color>");
				}
				else
				{
					__result += StringExt.Localize($"\n<color={UIColor.MinorInfo}>$info_fertile</color>");
				}
			}
		}
	}
	public static class Configs
	{
		internal static readonly ConfigEntry<Breeding.SterilizeType> Sterilization;

		internal static readonly ConfigEntry<StringList> BreedingAllowed;

		static Configs()
		{
			Sterilization = Config.Define<Breeding.SterilizeType>(true, "Breeding", "Sterilize", Breeding.SterilizeType.BabiesOnly, "Prevent exponential reproduction of tamed creatures.\n- None: No protection, Vanilla behavior\n- All: Remove all reproduction from adults and offspring. No reproduction allowed.\n- BabiesOnly: Babies are sterilized. However, wild creatures which are tamed will still be able to produce offspring.\nChicken Eggs are a special case, the eggs purchased from the Trader will produce a fertile Hen that can become pregnant if another hen is nearby.\nHowever, any laid eggs will produce a sterile Hen.");
			BreedingAllowed = Config.Define<StringList>(true, "Breeding", "Allowed Creatures", StringList.Empty, "Comma separated list of prefabs that are allowed to reproduce when sterilization is enabled.");
		}
	}
	[BepInPlugin("ZenDragon.ZenBreeding", "ZenBreeding", "0.2.4")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	internal class Plugin : ZenMod<Plugin>
	{
		public const string PluginName = "ZenBreeding";

		public const string PluginVersion = "0.2.4";

		public const string PluginGUID = "ZenDragon.ZenBreeding";

		protected override void Setup()
		{
			((ZenMod)this).RegisterCraftingItems += Breeding.AddEgg;
			((ZenMod)this).ConfigSync += Breeding.InitPrefabs;
		}

		protected override void TitleScene(bool isFirstBoot)
		{
		}

		protected override void WorldStart()
		{
		}

		protected override void Shutdown()
		{
		}
	}
}