Please disclose if your mod was created primarily using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of ZenBreeding v0.5.3
plugins/ZenBreeding.dll
Decompiled a week agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security.Permissions; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Jotunn.Utils; using Microsoft.CodeAnalysis; using UnityEngine; using Zen; using Zen.Interop; using Zen.Lib; using Zen.Lib.Config; [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.5.3")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.5.3.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] internal static class Breeding { internal enum SterilizeType { None, All, BabiesOnly } private static readonly int ZDOVarSterile = StringExtensionMethods.GetStableHashCode("ZenBreeding_Sterile"); private const string LaidEgg = "Zen_LaidEgg"; private const int LaidEggStackID = 100; private const string SterileText = "$info_sterile"; private const string FertileText = "$info_fertile"; private const string PregnantText = "$info_pregnant"; private static readonly Sprite FertileIcon = AssetIO.LoadSpriteFromResource((BaseUnityPlugin)(object)ZenMod<Plugin>.Instance, "heart.png"); private static bool IsSterile(this ZNetView? nview) { if (Object.op_Implicit((Object)(object)nview) && nview.IsValid()) { return nview.GetZDO().GetBool(ZDOVarSterile, false); } return false; } private static bool IsLaid(this EggGrow egg) { return egg.m_item.m_itemData.IsLaidEgg(); } private static bool IsLaidEgg(this ItemData egg) { return egg.m_customData.ContainsKey("Zen_LaidEgg"); } internal static void InitPrefabs() { if (Configs.Sterilization.Value == SterilizeType.All) { CollectionExtensions.Do<GameObject>((IEnumerable<GameObject>)ZNetScene.instance.m_prefabs, (Action<GameObject>)RemoveProcreate); } } 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); Logging<Plugin>.Message((object)("Sterilized prefab: " + ((Object)prefab).name), 0); } } private static bool CanBreed(Character c) { return CanBreed(GameObjectExt.GetPrefabName(((Component)c).gameObject)); } private static bool CanBreed(EggGrow egg) { return CanBreed(GameObjectExt.GetPrefabName(((Component)egg).gameObject)); } private static bool CanBreed(ItemDrop item) { return CanBreed(ItemDataExt.GetPrefabName(item)); } private static bool CanBreed(string prefabName) { if (Configs.Sterilization.Value != 0) { return Configs.BreedingAllowed.Value.Contains(prefabName, true); } return true; } [HarmonyPostfix] [HarmonyPatch(typeof(Procreation), "ReadyForProcreation")] private static void Procreation_ReadyForProcreation(Procreation __instance, ref bool __result) { if (__instance.m_nview.IsValid()) { __result = __result && !__instance.m_nview.IsSterile(); } } [HarmonyPrefix] [HarmonyPatch(typeof(Procreation), "MakePregnant")] private static void Procreation_MakePregnant(Procreation __instance, ref bool __runOriginal) { if (__instance.m_nview.IsValid()) { __runOriginal = !__instance.m_nview.IsSterile(); } } [HarmonyTranspiler] [HarmonyPatch(typeof(EggGrow), "GrowUpdate")] private static IEnumerable<CodeInstruction> EggGrow_GrowUpdate_Transpiler(IEnumerable<CodeInstruction> codes) { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Expected O, but got Unknown //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Expected O, but got Unknown Func<Character, EggGrow, bool> func = EggGrow_Intercept; CodeMatch[] array = (CodeMatch[])(object)new CodeMatch[3] { CodeMatch.op_Implicit(OpCodes.Ldloc_1), new CodeMatch((OpCode?)OpCodes.Call, (object)AccessTools.Method(typeof(Object), "op_Implicit", (Type[])null, (Type[])null), (string)null), CodeMatch.op_Implicit(OpCodes.Brfalse) }; return new CodeMatcher(codes, (ILGenerator)null).MatchStartForward(array).ThrowIfInvalid("Unable to match IL").Advance(1) .InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1] { new CodeInstruction(OpCodes.Ldarg_0, (object)null) }) .Set(OpCodes.Call, (object)func.Method) .InstructionEnumeration(); } private static bool EggGrow_Intercept(Character? hatchling, EggGrow egg) { if (!Object.op_Implicit((Object)(object)hatchling)) { return false; } if (CanBreed(egg)) { return true; } if (egg.IsLaid()) { Sterilize(hatchling); } return true; } [HarmonyTranspiler] [HarmonyPatch(typeof(Growup), "GrowUpdate")] private static IEnumerable<CodeInstruction> GrowUp_GrowUpdate_Transpiler(IEnumerable<CodeInstruction> codes) { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Expected O, but got Unknown //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Expected O, but got Unknown //IL_00ab: Unknown result type (might be due to invalid IL or missing references) Func<Character, Character, bool> func = GrowUp_Intercept; CodeMatch[] array = (CodeMatch[])(object)new CodeMatch[6] { CodeMatch.op_Implicit(OpCodes.Ldloc_1), new CodeMatch((OpCode?)OpCodes.Call, (object)AccessTools.Method(typeof(Object), "op_Implicit", (Type[])null, (Type[])null), (string)null), CodeMatch.op_Implicit(OpCodes.Brfalse), CodeMatch.op_Implicit(OpCodes.Ldloc_2), new CodeMatch((OpCode?)OpCodes.Call, (object)AccessTools.Method(typeof(Object), "op_Implicit", (Type[])null, (Type[])null), (string)null), CodeMatch.op_Implicit(OpCodes.Brfalse) }; return new CodeMatcher(codes, (ILGenerator)null).MatchStartForward(array).ThrowIfInvalid("Unable to match IL").Advance(1) .SetAndAdvance(OpCodes.Nop, (object)null) .SetAndAdvance(OpCodes.Nop, (object)null) .Advance(1) .Set(OpCodes.Call, (object)func.Method) .InstructionEnumeration(); } private static bool GrowUp_Intercept(Character young, Character mature) { if (!Object.op_Implicit((Object)(object)young) || !Object.op_Implicit((Object)(object)mature)) { return false; } if (CanBreed(mature)) { return true; } if (young.m_nview.IsSterile()) { Sterilize(mature); } return true; } [HarmonyTranspiler] [HarmonyPatch(typeof(Procreation), "Procreate")] private static IEnumerable<CodeInstruction> Procreation_Procreate_Transpiler(IEnumerable<CodeInstruction> codes) { MethodInfo methodInfo = AccessTools.Method(typeof(Character), "SetLevel", (Type[])null, (Type[])null); Action<Character, int> action = Procreate_SetLevel_Intercept; MethodInfo methodInfo2 = AccessTools.Method(typeof(ItemDrop), "SetQuality", (Type[])null, (Type[])null); Action<ItemDrop, int> action2 = Procreate_SetQuality_Intercept; return Transpilers.MethodReplacer(Transpilers.MethodReplacer(codes, (MethodBase)methodInfo, (MethodBase)action.Method), (MethodBase)methodInfo2, (MethodBase)action2.Method); } private static void Procreate_SetLevel_Intercept(Character baby, int level) { baby.SetLevel(level); ProcreateBaby(baby); } private static void Procreate_SetQuality_Intercept(ItemDrop item, int quality) { item.SetQuality(quality); ProcreateEgg(item); } private static void ProcreateBaby(Character baby) { if (!CanBreed(baby)) { Sterilize(baby); } } private static void ProcreateEgg(ItemDrop egg) { SetEggState(egg.m_itemData, isLaid: true, !CanBreed(egg)); } internal static void SetEggState(ItemData egg, bool isLaid, bool separateStacks) { egg.m_worldLevel = (separateStacks ? 100 : Game.m_worldLevel); if (isLaid) { egg.m_customData["Zen_LaidEgg"] = true.ToString(); } else { egg.m_customData.Remove("Zen_LaidEgg"); } } private static void Sterilize(Character offspring) { //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) Logging<Plugin>.Info((object)$"Sterilize {((Object)offspring).name} {MathExt.XZY(((Component)offspring).transform.position)}", 0); if (offspring.m_nview.IsOwner()) { offspring.m_nview.GetZDO().Set(ZDOVarSterile, true); } } [HarmonyPostfix] [HarmonyPatch(typeof(Tameable), "GetHoverText")] [HarmonyPriority(100)] private static void Tameable_GetHoverText(Tameable __instance, ref string __result) { Procreation val = default(Procreation); if (__instance.IsTamed() && !__instance.m_nview.IsSterile() && ((Component)__instance).TryGetComponent<Procreation>(ref val) && ((Behaviour)val).enabled) { HoverItem.UpdateIcons((Sprite[])(object)new Sprite[1] { FertileIcon }); if (val.IsPregnant()) { __result += StringExt.Localize(string.Format("\n<color={0}>{1}</color>", UIColor.MajorInfo, "$info_pregnant")); } else { __result += StringExt.Localize(string.Format("\n<color={0}>{1}</color>", UIColor.MinorInfo, "$info_fertile")); } } } [HarmonyPostfix] [HarmonyPatch(typeof(ItemDrop), "GetHoverText")] [HarmonyPriority(100)] private static void ItemDrop_GetHoverText(ItemDrop __instance, ref string __result) { if (__instance.m_itemData.IsLaidEgg()) { __result += StringExt.Localize(string.Format("\n\n<color={0}>{1}</color>", UIColor.MajorInfo, "$info_sterile")); } } [HarmonyPostfix] [HarmonyPatch(typeof(ItemData), "GetTooltip", new Type[] { typeof(int) })] private static void ItemDrop_ItemData_GetTooltip(ItemData __instance, ref string __result) { if (!__instance.IsLaidEgg()) { ItemDataExt.SetTooltipExtra(__instance, (string)null); return; } string description = __instance.m_shared.m_description; ItemDataExt.SetTooltipExtra(__instance, "$info_sterile"); __result = Regex.Replace(__result, "\\$item_newgameplusitem.*\n", string.Empty); __result = __result.Replace(description, string.Format("{0}\n\n<color={1}>{2}</color>", description, UIColor.Orange, "$info_sterile")); } } internal static class BreedingCommands { private const string CmdSterilize = "sterilize"; private const string CmdFertilize = "fertilize"; private static List<ItemData> Inventory { get { Player localPlayer = Player.m_localPlayer; return ((localPlayer != null) ? ((Humanoid)localPlayer).GetInventory().GetAllItems() : null) ?? new List<ItemData>(); } } private static string Syntax(string command) { return command + " <EggPrefabName>"; } public static void Init() { ZenMod<Plugin>.Terminal.CreateCommand("sterilize", "Sterilize egg in your inventory", true, (Action<string[]>)ProcessEgg); ZenMod<Plugin>.Terminal.CreateCommand("fertilize", "Fertilize egg in you inventory", true, (Action<string[]>)ProcessEgg); } private static ItemData[] FindItems(string name) { string name2 = name; return Inventory.Where((ItemData item) => ItemDataExt.GetPrefabName(item).ToLower() == name2.ToLower()).ToArray(); } private static void ProcessEgg(params string[] args) { if (args.Length < 2) { Console.instance.Print(Syntax(args[0])); return; } string text = args[0].ToLower().Replace("Zen_".ToLower(), string.Empty); string text2 = args[1]; ItemData[] array = FindItems(text2); if (array.Length == 0) { Console.instance.Print("No item found: " + text2); return; } bool flag; if (!(text == "sterilize")) { if (!(text == "fertilize")) { throw new Exception("Unknown command: " + text); } flag = false; } else { flag = true; } bool flag2 = flag; int num = 0; ItemData[] array2 = array; foreach (ItemData val in array2) { Breeding.SetEggState(val, flag2, flag2); num += val.m_stack; } Console.instance.Print($"{StringExt.ToProperCase(text, true)} {num} {text2}"); } } internal static class Configs { public static readonly ConfigEntry<Breeding.SterilizeType> Sterilization; public static readonly ConfigEntry<StringList> BreedingAllowed; static Configs() { Sterilization = Config.Define<Breeding.SterilizeType>(true, "Breeding", "Sterilize", Breeding.SterilizeType.BabiesOnly, "Prevent exponential reproduction of tamed creatures.\r\n- None: No protection, Vanilla behavior\r\n- All: Remove all reproduction from adults and offspring. No reproduction allowed.\r\n- BabiesOnly: Babies are sterilized. However, wild creatures which are tamed will still be able to produce offspring.\r\nNOTE: Eggs that are discovered or purchased will produce a fertile Hen. That hen can produce eggs.\r\nHowever, any laid eggs will produce a sterile Hen that can not produce eggs.\r\nTIP: When you are in admin/god mode you can glance at the fertility of eggs on the ground."); BreedingAllowed = Config.Define<StringList>(true, "Breeding", "Allowed Creatures", StringList.Empty, "Comma separated list of prefabs that are allowed to reproduce when sterilization is enabled.\r\nFor example: If you add \"ChickenEgg\" to this list then chicken eggs will grow into fertile chickens that can lay eggs.\r\n[restart required for changes to take effect]"); } } [BepInPlugin("ZenDragon.ZenBreeding", "ZenBreeding", "0.5.3")] [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.5.3"; public const string PluginGUID = "ZenDragon.ZenBreeding"; protected override void Setup() { base.ConfigSync += Breeding.InitPrefabs; BreedingCommands.Init(); } protected override void TitleScene(bool isFirstBoot) { } protected override void WorldStart() { } protected override void Shutdown() { } } }