Please disclose if any significant portion of your mod was created 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 BabyTames v1.0.1
BepInEx/plugins/BabyTames.dll
Decompiled 5 days agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("BabyTames")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.1.0")] [assembly: AssemblyInformationalVersion("1.0.1")] [assembly: AssemblyProduct("BabyTames")] [assembly: AssemblyTitle("BabyTames")] [assembly: AssemblyVersion("1.0.1.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 BabyTames { internal static class Babies { private static readonly int KeepBabyKey = StringExtensionMethods.GetStableHashCode("BabyTames_KeepBaby"); private static readonly int FrozenAgeKey = StringExtensionMethods.GetStableHashCode("BabyTames_FrozenAge"); private static readonly FieldRef<Character, ZNetView> CharacterView = AccessTools.FieldRefAccess<Character, ZNetView>("m_nview"); private static readonly FieldRef<Player, Character> HoveringCreature = AccessTools.FieldRefAccess<Player, Character>("m_hoveringCreature"); private static readonly Func<Player, bool> TakeInput = AccessTools.MethodDelegate<Func<Player, bool>>(AccessTools.Method(typeof(Player), "TakeInput", (Type[])null, (Type[])null), (object)null, true); private static readonly Action<BaseAI, GameObject, float> Follow = AccessTools.MethodDelegate<Action<BaseAI, GameObject, float>>(AccessTools.Method(typeof(BaseAI), "Follow", (Type[])null, (Type[])null), (object)null, true); private static readonly Regex GrowthLine = new Regex("^(Grows up in .*|Growing up)$", RegexOptions.Multiline); private const string StayingBaby = "Staying a baby"; private static string pendingName; private static string pendingNameAuthor; private static string pendingFollow; internal static ZNetView ViewOf(Character character) { return CharacterView.Invoke(character); } internal static bool IsBaby(Character character) { if ((Object)(object)character == (Object)null) { return false; } ZNetView val = CharacterView.Invoke(character); if ((Object)(object)val != (Object)null && val.IsValid()) { return Plugin.BabyHashes.Contains(val.GetZDO().GetPrefab()); } return false; } internal static bool IsTameBaby(Character character) { if (IsBaby(character)) { return character.IsTamed(); } return false; } internal static bool IsKept(ZDO zdo) { return zdo.GetBool(KeepBabyKey, false); } internal static Character Hovered(Player player) { return HoveringCreature.Invoke(player); } internal static void SetUpPrefabs(ZNetScene scene) { foreach (GameObject prefab in scene.m_prefabs) { if ((Object)(object)prefab == (Object)null || !Plugin.BabyHashes.Contains(StringExtensionMethods.GetStableHashCode(((Object)prefab).name))) { continue; } if ((Object)(object)prefab.GetComponent<Character>() == (Object)null || (Object)(object)prefab.GetComponent<BaseAI>() == (Object)null) { Plugin.Log.LogWarning((object)(((Object)prefab).name + " is not a creature with an AI, skipping")); continue; } Tameable val = prefab.GetComponent<Tameable>(); if ((Object)(object)val == (Object)null) { val = prefab.AddComponent<Tameable>(); CopyFromGrown(prefab, val); } if (Plugin.CommandableBabies.Value) { val.m_commandable = true; } } } private static void CopyFromGrown(GameObject baby, Tameable tameable) { Growup component = baby.GetComponent<Growup>(); Tameable val = (((Object)(object)component != (Object)null && (Object)(object)component.m_grownPrefab != (Object)null) ? component.m_grownPrefab.GetComponent<Tameable>() : null); if (!((Object)(object)val == (Object)null)) { tameable.m_fedDuration = val.m_fedDuration; tameable.m_tamingTime = val.m_tamingTime; tameable.m_petEffect = val.m_petEffect; tameable.m_sootheEffect = val.m_sootheEffect; tameable.m_tameText = val.m_tameText; tameable.m_nameBeforeText = val.m_nameBeforeText; } } internal static void Tick() { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || !TakeInput(localPlayer)) { return; } KeyboardShortcut value = Plugin.KeepBabyKey.Value; if (((KeyboardShortcut)(ref value)).IsDown()) { Character val = Hovered(localPlayer); if (IsTameBaby(val) && !((Object)(object)((Component)val).GetComponent<Growup>() == (Object)null)) { Toggle(localPlayer, val); } } } private static void Toggle(Player player, Character baby) { ZNetView obj = CharacterView.Invoke(baby); obj.ClaimOwnership(); ZDO zDO = obj.GetZDO(); bool flag = !IsKept(zDO); if (flag) { Growup component = ((Component)baby).GetComponent<Growup>(); BaseAI baseAI = baby.GetBaseAI(); float num = (((Object)(object)baseAI != (Object)null) ? ((float)baseAI.GetTimeSinceSpawned().TotalSeconds) : 0f); num = Mathf.Clamp(num, 0f, Mathf.Max(0f, component.m_growTime - 30f)); zDO.Set(FrozenAgeKey, num); zDO.Set(KeepBabyKey, true); PinAge(zDO); } else { PinAge(zDO); zDO.Set(KeepBabyKey, false); } ((Character)player).Message((MessageType)2, baby.GetHoverName() + (flag ? " will stay a baby" : " will grow up"), 0, (Sprite)null, false); } private static void PinAge(ZDO zdo) { long ticks = TimeSpan.FromSeconds(zdo.GetFloat(FrozenAgeKey, 0f)).Ticks; zdo.Set(ZDOVars.s_spawnTime, ZNet.instance.GetTime().Ticks - ticks); } internal static bool BeforeGrowUpdate(Growup growup) { pendingName = null; pendingNameAuthor = null; pendingFollow = null; Character component = ((Component)growup).GetComponent<Character>(); if (!IsTameBaby(component)) { return true; } ZNetView val = CharacterView.Invoke(component); if (!val.IsOwner()) { return true; } ZDO zDO = val.GetZDO(); if (IsKept(zDO)) { PinAge(zDO); return false; } if (Plugin.CarryOverOnGrowUp.Value) { pendingName = zDO.GetString(ZDOVars.s_tamedName, ""); pendingNameAuthor = zDO.GetString(ZDOVars.s_tamedNameAuthor, ""); pendingFollow = zDO.GetString(ZDOVars.s_follow, ""); } return true; } internal static void AfterGrowUpdate() { pendingName = null; pendingNameAuthor = null; pendingFollow = null; } internal static void OnTameableAwake(Tameable tameable) { if (pendingName == null) { return; } ZNetView component = ((Component)tameable).GetComponent<ZNetView>(); if (!((Object)(object)component == (Object)null) && component.IsValid() && component.IsOwner()) { ZDO zDO = component.GetZDO(); if (pendingName.Length > 0) { zDO.Set(ZDOVars.s_tamedName, pendingName); zDO.Set(ZDOVars.s_tamedNameAuthor, pendingNameAuthor); } if (pendingFollow.Length > 0) { zDO.Set(ZDOVars.s_follow, pendingFollow); } pendingName = null; } } internal static string AddHoverLines(Character character, string hoverText) { //IL_00a9: Unknown result type (might be due to invalid IL or missing references) if (hoverText.Length == 0 || !IsTameBaby(character) || (Object)(object)((Component)character).GetComponent<Growup>() == (Object)null) { return hoverText; } bool flag = IsKept(CharacterView.Invoke(character).GetZDO()); if (flag) { if (GrowthLine.IsMatch(hoverText)) { hoverText = GrowthLine.Replace(hoverText, "Staying a baby"); } else { int num = hoverText.IndexOf('\n'); hoverText = ((num >= 0) ? (hoverText.Substring(0, num) + "\nStaying a baby" + hoverText.Substring(num)) : (hoverText + "\nStaying a baby")); } } return hoverText + "\n[<color=yellow><b>" + KeyText(Plugin.KeepBabyKey.Value) + "</b></color>] Keep Baby: " + (flag ? "On" : "Off"); } internal static bool SwallowsInteract(Tameable tameable) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) KeyboardShortcut value = Plugin.KeepBabyKey.Value; if (((KeyboardShortcut)(ref value)).IsPressed()) { return IsTameBaby(((Component)tameable).GetComponent<Character>()); } return false; } internal static bool IsHungryOverride(Tameable tameable) { if (!IsTameBaby(((Component)tameable).GetComponent<Character>())) { return false; } MonsterAI component = ((Component)tameable).GetComponent<MonsterAI>(); if (!((Object)(object)component == (Object)null) && component.m_consumeItems != null) { return component.m_consumeItems.Count == 0; } return true; } internal static bool HandleCommand(Tameable tameable, ZDOID characterID, bool message) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)((Component)tameable).GetComponent<MonsterAI>() != (Object)null) { return true; } Character component = ((Component)tameable).GetComponent<Character>(); if (!IsTameBaby(component)) { return true; } GameObject val = ZNetScene.instance.FindInstance(characterID); Player val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<Player>() : null); ZNetView val3 = CharacterView.Invoke(component); if ((Object)(object)val2 == (Object)null || !val3.IsOwner()) { return false; } ZDO zDO = val3.GetZDO(); bool flag = zDO.GetString(ZDOVars.s_follow, "").Length == 0; zDO.Set(ZDOVars.s_follow, flag ? val2.GetPlayerName() : ""); if (message) { ((Character)val2).Message((MessageType)2, tameable.GetHoverName() + (flag ? " $hud_tamefollow" : " $hud_tamestay"), 0, (Sprite)null, false); } return false; } internal static void AfterAnimalUpdate(AnimalAI ai, float dt, bool updated) { if (!updated) { return; } Character component = ((Component)ai).GetComponent<Character>(); if (!IsTameBaby(component)) { return; } string text = CharacterView.Invoke(component).GetZDO().GetString(ZDOVars.s_follow, ""); if (text.Length == 0) { return; } foreach (Player allPlayer in Player.GetAllPlayers()) { if (allPlayer.GetPlayerName() == text) { Follow((BaseAI)(object)ai, ((Component)allPlayer).gameObject, dt); break; } } } internal static bool BlocksDamage(Character character, HitData hit) { if (!Plugin.InvincibleBabies.Value || !IsTameBaby(character)) { return false; } if (Plugin.ButcherKnifeKills.Value && hit != null) { Character attacker = hit.GetAttacker(); Humanoid val = (Humanoid)(object)((attacker is Humanoid) ? attacker : null); if (val != null && ((Character)val).IsPlayer()) { ItemData currentWeapon = val.GetCurrentWeapon(); if (currentWeapon != null && currentWeapon.m_shared.m_tamedOnly) { return false; } } } return true; } private static string KeyText(KeyboardShortcut shortcut) { //IL_0016: 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_001d: 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) string text = ""; foreach (KeyCode modifier in ((KeyboardShortcut)(ref shortcut)).Modifiers) { text = text + KeyName(modifier) + " + "; } return text + KeyName(((KeyboardShortcut)(ref shortcut)).MainKey); } private unsafe static string KeyName(KeyCode key) { //IL_0000: 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_0024: Expected I4, but got Unknown switch (key - 303) { case 4: case 5: return "Alt"; case 0: case 1: return "Shift"; case 2: case 3: return "Ctrl"; default: return ((object)(*(KeyCode*)(&key))/*cast due to .constrained prefix*/).ToString(); } } } internal static class BetterTamesCompat { internal const string BetterTamesGuid = "xtav1m.BetterTames"; internal static void Install(Harmony harmony) { if (Chainloader.PluginInfos.ContainsKey("xtav1m.BetterTames")) { Type type = AccessTools.TypeByName("BetterTames.Scripts.Protection.Protection"); if (type == null) { Plugin.Log.LogWarning((object)"Better Tames found, but not its Protection class; its Alt + E toggle may also fire on babies"); return; } Patch(harmony, type, "Tick", "Tick_Prefix"); Patch(harmony, type, "AddPrompt", "AddPrompt_Prefix"); } } private static void Patch(Harmony harmony, Type type, string method, string prefix) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Expected O, but got Unknown MethodInfo methodInfo = AccessTools.Method(type, method, (Type[])null, (Type[])null); if (methodInfo == null) { Plugin.Log.LogWarning((object)("Better Tames method " + method + " not found, skipping")); } else { harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(BetterTamesCompat), prefix, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } private static bool Tick_Prefix() { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null)) { return !Babies.IsTameBaby(Babies.Hovered(localPlayer)); } return true; } private static bool AddPrompt_Prefix(Character character, string hoverText, ref string __result) { if (!Babies.IsTameBaby(character)) { return true; } __result = hoverText; return false; } } [HarmonyPatch] internal static class Patches { [HarmonyPostfix] [HarmonyPatch(typeof(ZNetScene), "Awake")] private static void ZNetScene_Awake_Postfix(ZNetScene __instance) { Babies.SetUpPrefabs(__instance); } [HarmonyPrefix] [HarmonyPatch(typeof(Growup), "GrowUpdate")] private static bool Growup_GrowUpdate_Prefix(Growup __instance) { return Babies.BeforeGrowUpdate(__instance); } [HarmonyPostfix] [HarmonyPatch(typeof(Growup), "GrowUpdate")] private static void Growup_GrowUpdate_Postfix() { Babies.AfterGrowUpdate(); } [HarmonyPostfix] [HarmonyPatch(typeof(Tameable), "Awake")] private static void Tameable_Awake_Postfix(Tameable __instance) { Babies.OnTameableAwake(__instance); } [HarmonyPrefix] [HarmonyPatch(typeof(Tameable), "Interact")] private static bool Tameable_Interact_Prefix(Tameable __instance, ref bool __result) { if (!Babies.SwallowsInteract(__instance)) { return true; } __result = true; return false; } [HarmonyPrefix] [HarmonyPatch(typeof(Tameable), "RPC_Command")] private static bool Tameable_RPC_Command_Prefix(Tameable __instance, ZDOID characterID, bool message) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return Babies.HandleCommand(__instance, characterID, message); } [HarmonyPostfix] [HarmonyPatch(typeof(AnimalAI), "UpdateAI")] private static void AnimalAI_UpdateAI_Postfix(AnimalAI __instance, float dt, bool __result) { Babies.AfterAnimalUpdate(__instance, dt, __result); } [HarmonyPostfix] [HarmonyPatch(typeof(Tameable), "IsHungry")] private static void Tameable_IsHungry_Postfix(Tameable __instance, ref bool __result) { if (__result && Babies.IsHungryOverride(__instance)) { __result = false; } } [HarmonyPostfix] [HarmonyPriority(0)] [HarmonyPatch(typeof(Character), "GetHoverText")] private static void Character_GetHoverText_Postfix(Character __instance, ref string __result) { __result = Babies.AddHoverLines(__instance, __result); } [HarmonyPrefix] [HarmonyPatch(typeof(Character), "RPC_Damage")] private static bool Character_RPC_Damage_Prefix(Character __instance, HitData hit) { return !Babies.BlocksDamage(__instance, hit); } } [BepInPlugin("taylor.babytames", "Baby Tames", "1.0.1")] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class Plugin : BaseUnityPlugin { public const string Guid = "taylor.babytames"; public const string Name = "Baby Tames"; public const string Version = "1.0.1"; private const string GeneralSection = "1 - General"; private const string GrowthSection = "2 - Growth"; private const string ProtectionSection = "3 - Protection"; internal const string DefaultBabies = "Boar_piggy, Wolf_cub, Chicken, Lox_Calf, Asksvin_hatchling, Moose_calf"; internal static ManualLogSource Log; internal static ConfigEntry<string> BabyPrefabs; internal static ConfigEntry<bool> CommandableBabies; internal static ConfigEntry<KeyboardShortcut> KeepBabyKey; internal static ConfigEntry<bool> CarryOverOnGrowUp; internal static ConfigEntry<bool> InvincibleBabies; internal static ConfigEntry<bool> ButcherKnifeKills; internal static readonly HashSet<int> BabyHashes = new HashSet<int>(); private Harmony harmony; private void Awake() { //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; BabyPrefabs = ((BaseUnityPlugin)this).Config.Bind<string>("1 - General", "Baby Prefabs", "Boar_piggy, Wolf_cub, Chicken, Lox_Calf, Asksvin_hatchling, Moose_calf", "Comma-separated prefab names (case sensitive) of the baby creatures this mod applies to. Changes to this list take effect after a restart."); CommandableBabies = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - General", "Babies Follow", true, "Pressing E on a tamed baby makes it follow you or stay, like a grown tame. Better Tames' Command Any Tame setting can also turn this on."); KeepBabyKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("2 - Growth", "Keep Baby Key", new KeyboardShortcut((KeyCode)101, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), "Switch the tame baby you are looking at between growing up and staying a baby."); CarryOverOnGrowUp = ((BaseUnityPlugin)this).Config.Bind<bool>("2 - Growth", "Keep Name And Follow On Grow Up", true, "A baby that grows up keeps the name you gave it, and keeps following you if it was."); InvincibleBabies = ((BaseUnityPlugin)this).Config.Bind<bool>("3 - Protection", "Invincible Babies", true, "Tamed babies take no damage."); ButcherKnifeKills = ((BaseUnityPlugin)this).Config.Bind<bool>("3 - Protection", "Butcher Knife Still Kills", true, "A butcher knife can still hurt an invincible baby."); string[] array = BabyPrefabs.Value.Split(','); for (int i = 0; i < array.Length; i++) { string text = array[i].Trim(); if (text.Length > 0) { BabyHashes.Add(StringExtensionMethods.GetStableHashCode(text)); } } harmony = new Harmony("taylor.babytames"); harmony.PatchAll(); BetterTamesCompat.Install(harmony); } private void Update() { Babies.Tick(); } private void OnDestroy() { Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } } } }