Decompiled source of MyBearFriend v0.1.0

MyBearFriend.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
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 Jotunn;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("MyBearFriend")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("MyBearFriend")]
[assembly: AssemblyCopyright("Copyright ©  2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.0.0")]
namespace MyBearFriend;

internal static class LocalizationHelper
{
	private static readonly List<string> languages = new List<string>
	{
		"English", "Swedish", "French", "Italian", "German", "Spanish", "Russian", "Romanian", "Bulgarian", "Macedonian",
		"Finnish", "Danish", "Norwegian", "Icelandic", "Turkish", "Lithuanian", "Czech", "Hungarian", "Slovak", "Polish",
		"Dutch", "Portuguese_European", "Portuguese_Brazilian", "Chinese", "Chinese_Trad", "Japanese", "Korean", "Hindi", "Thai", "Abenaki",
		"Croatian", "Georgian", "Greek", "Serbian", "Ukrainian", "Latvian"
	};

	public static bool IsLanguageSupported(string language)
	{
		return languages.Contains(language);
	}
}
[BepInPlugin("com.milkwyzard.MyBearFriend", "MyBearFriend", "0.1.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
public class MyBearFriend : BaseUnityPlugin
{
	[CompilerGenerated]
	private sealed class <EnumerateConsumables>d__22 : IEnumerable<string>, IEnumerable, IEnumerator<string>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private string <>2__current;

		private int <>l__initialThreadId;

		private ConfigEntry<string> configConsumables;

		public ConfigEntry<string> <>3__configConsumables;

		private string[] <>7__wrap1;

		private int <>7__wrap2;

		string IEnumerator<string>.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		object IEnumerator.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		[DebuggerHidden]
		public <EnumerateConsumables>d__22(int <>1__state)
		{
			this.<>1__state = <>1__state;
			<>l__initialThreadId = Environment.CurrentManagedThreadId;
		}

		[DebuggerHidden]
		void IDisposable.Dispose()
		{
			<>7__wrap1 = null;
			<>1__state = -2;
		}

		private bool MoveNext()
		{
			switch (<>1__state)
			{
			default:
				return false;
			case 0:
			{
				<>1__state = -1;
				string[] array = configConsumables.Value.Split(new char[1] { ';' }, StringSplitOptions.RemoveEmptyEntries);
				<>7__wrap1 = array;
				<>7__wrap2 = 0;
				break;
			}
			case 1:
				<>1__state = -1;
				<>7__wrap2++;
				break;
			}
			if (<>7__wrap2 < <>7__wrap1.Length)
			{
				string text = <>7__wrap1[<>7__wrap2];
				<>2__current = text.Trim();
				<>1__state = 1;
				return true;
			}
			<>7__wrap1 = null;
			return false;
		}

		bool IEnumerator.MoveNext()
		{
			//ILSpy generated this explicit interface implementation from .override directive in MoveNext
			return this.MoveNext();
		}

		[DebuggerHidden]
		void IEnumerator.Reset()
		{
			throw new NotSupportedException();
		}

		[DebuggerHidden]
		IEnumerator<string> IEnumerable<string>.GetEnumerator()
		{
			<EnumerateConsumables>d__22 <EnumerateConsumables>d__;
			if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
			{
				<>1__state = 0;
				<EnumerateConsumables>d__ = this;
			}
			else
			{
				<EnumerateConsumables>d__ = new <EnumerateConsumables>d__22(0);
			}
			<EnumerateConsumables>d__.configConsumables = <>3__configConsumables;
			return <EnumerateConsumables>d__;
		}

		[DebuggerHidden]
		IEnumerator IEnumerable.GetEnumerator()
		{
			return ((IEnumerable<string>)this).GetEnumerator();
		}
	}

	public const string PluginGUID = "com.milkwyzard.MyBearFriend";

	public const string PluginName = "MyBearFriend";

	public const string PluginVersion = "0.1.0";

	public static CustomLocalization Localization = LocalizationManager.Instance.GetLocalization();

	private const string bearNameLocalizedFormat = "name_randBearName";

	private Harmony harmony;

	private int randomNameCount;

	private bool creaturesAvailable;

	private bool prefabsAvailable;

	public static ConfigEntry<string> BearConsumableItems;

	public static ConfigEntry<float> BearTameTime;

	public static ConfigEntry<float> BearFedDuration;

	public MyBearFriend()
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0016: Expected O, but got Unknown
		harmony = new Harmony("com.milkwyzard.MyBearFriend");
	}

	public void Start()
	{
		harmony.PatchAll(Assembly.GetExecutingAssembly());
	}

	private void Awake()
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Expected O, but got Unknown
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_003c: Expected O, but got Unknown
		//IL_0074: Unknown result type (might be due to invalid IL or missing references)
		//IL_007e: Expected O, but got Unknown
		//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c0: Expected O, but got Unknown
		ConfigurationManagerAttributes val = new ConfigurationManagerAttributes
		{
			IsAdminOnly = true
		};
		BearConsumableItems = ((BaseUnityPlugin)this).Config.Bind<string>("General", "BearConsumableItems", "Blueberries; Honey; RawMeat; DeerMeat", new ConfigDescription("Items that the Bear can consume/eat. Must be the name of the prefab. See Jotunn docs.", (AcceptableValueBase)null, new object[1] { val }));
		BearTameTime = ((BaseUnityPlugin)this).Config.Bind<float>("General", "BearTameTime", 1600f, new ConfigDescription("Amount of time (in seconds) it takes to tame a Bear (default is slightly less than wolf).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10000f), new object[1] { val }));
		BearFedDuration = ((BaseUnityPlugin)this).Config.Bind<float>("General", "BearFedDuration", 400f, new ConfigDescription("Amount of time (in seconds) after feeding a Bear before it becomes hungry again (default is slightly less than wolf).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1000f), new object[1] { val }));
		CreatureManager.OnVanillaCreaturesAvailable += OnVanillaCreaturesAvailable;
		PrefabManager.OnVanillaPrefabsAvailable += OnVanillaPrefabsAvailable;
		LocalizationManager.OnLocalizationAdded += OnLocalizationsAdded;
		Logger.LogInfo((object)"MyBearFriend v0.1.0 loaded and patched.");
	}

	private void OnLocalizationsAdded()
	{
		ResolveLocalizations();
		string text = Localization.GetLanguages().FirstOrDefault();
		if (text != null)
		{
			randomNameCount = Localization.GetTranslations(ref text).Count((KeyValuePair<string, string> kvp) => kvp.Key.StartsWith("name_randBearName"));
			Logger.LogWarning((object)$"Random name count: {randomNameCount}");
		}
	}

	private void OnVanillaPrefabsAvailable()
	{
		prefabsAvailable = true;
		if (prefabsAvailable && creaturesAvailable)
		{
			MakeBearTameable();
		}
	}

	private void OnVanillaCreaturesAvailable()
	{
		creaturesAvailable = true;
		if (prefabsAvailable && creaturesAvailable)
		{
			MakeBearTameable();
		}
	}

	private void MakeBearTameable()
	{
		//IL_016b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0254: Unknown result type (might be due to invalid IL or missing references)
		//IL_0259: Unknown result type (might be due to invalid IL or missing references)
		//IL_0295: Unknown result type (might be due to invalid IL or missing references)
		//IL_029a: Unknown result type (might be due to invalid IL or missing references)
		GameObject creaturePrefab = CreatureManager.Instance.GetCreaturePrefab("Wolf");
		if ((Object)(object)creaturePrefab == (Object)null)
		{
			Logger.LogWarning((object)"Could not Wolf creature prefab.");
			return;
		}
		Tameable component = creaturePrefab.GetComponent<Tameable>();
		if ((Object)(object)component == (Object)null)
		{
			Logger.LogWarning((object)"Could not find Tameable Component for the Wolf prefab.");
			return;
		}
		GameObject creaturePrefab2 = CreatureManager.Instance.GetCreaturePrefab("Bjorn");
		if ((Object)(object)creaturePrefab2 == (Object)null)
		{
			Logger.LogWarning((object)"Could not find Bear creature prefab.");
			return;
		}
		MonsterAI component2 = creaturePrefab2.GetComponent<MonsterAI>();
		if ((Object)(object)component2 == (Object)null)
		{
			Logger.LogWarning((object)"Expected Bear prefab to have Monster AI.");
			return;
		}
		component2.m_consumeItems.Clear();
		foreach (string item in EnumerateConsumables(BearConsumableItems))
		{
			AddConsumableItem(component2, item);
		}
		Tameable component3 = creaturePrefab2.GetComponent<Tameable>();
		if ((Object)(object)component3 != (Object)null)
		{
			Logger.LogWarning((object)"Expected Bear prefab to not have a Tameable component.");
			return;
		}
		if (component.m_tamedEffect.m_effectPrefabs.Length == 0 || component.m_petEffect.m_effectPrefabs.Length == 0 || component.m_sootheEffect.m_effectPrefabs.Length == 0)
		{
			Logger.LogWarning((object)"Could not get taming effect prefabs from Wolf prefab type.");
			return;
		}
		EffectData val = DuplicateEffectData(component.m_tamedEffect.m_effectPrefabs[0]);
		if (val == null)
		{
			return;
		}
		EffectData val2 = DuplicateEffectData(component.m_petEffect.m_effectPrefabs[0]);
		if (val2 != null)
		{
			EffectData val3 = DuplicateEffectData(component.m_sootheEffect.m_effectPrefabs[0]);
			if (val3 != null)
			{
				Logger.LogDebug((object)$"m_levelUpOwnerSkill - {component.m_levelUpOwnerSkill}");
				Logger.LogDebug((object)$"m_tamingTime - {component.m_tamingTime}");
				Logger.LogDebug((object)$"m_fedDuration - {component.m_fedDuration}");
				component3 = creaturePrefab2.AddComponent<Tameable>();
				component3.m_fedDuration = BearFedDuration.Value;
				component3.m_tamingTime = BearTameTime.Value;
				component3.m_startsTamed = false;
				component3.m_tamedEffect.m_effectPrefabs = (EffectData[])(object)new EffectData[1] { val };
				component3.m_sootheEffect.m_effectPrefabs = (EffectData[])(object)new EffectData[1] { val3 };
				component3.m_petEffect.m_effectPrefabs = (EffectData[])(object)new EffectData[1] { val2 };
				component3.m_commandable = component.m_commandable;
				component3.m_unsummonDistance = component.m_unsummonDistance;
				component3.m_unsummonOnOwnerLogoutSeconds = component.m_unsummonOnOwnerLogoutSeconds;
				component3.m_levelUpOwnerSkill = component.m_levelUpOwnerSkill;
				component3.m_levelUpFactor = component.m_levelUpFactor;
				component3.m_saddleItem = component.m_saddleItem;
				component3.m_saddle = component.m_saddle;
				component3.m_dropSaddleOnDeath = component.m_dropSaddleOnDeath;
				component3.m_dropSaddleOffset = component.m_dropSaddleOffset;
				component3.m_dropItemVel = component.m_dropItemVel;
				component3.m_tamingSpeedMultiplierRange = component.m_tamingSpeedMultiplierRange;
				component3.m_tamingBoostMultiplier = component.m_tamingBoostMultiplier;
				SetRandomStartingNames(component3);
			}
		}
	}

	private static void AddConsumableItem(MonsterAI monsterAi, string itemName)
	{
		ItemDrop val = null;
		GameObject prefab = PrefabManager.Instance.GetPrefab(itemName);
		if ((Object)(object)prefab != (Object)null)
		{
			val = prefab.GetComponent<ItemDrop>();
			if ((Object)(object)val != (Object)null)
			{
				monsterAi.m_consumeItems.Add(val);
			}
		}
		if ((Object)(object)val == (Object)null)
		{
			Logger.LogWarning((object)("Could not find item: " + itemName));
		}
		else
		{
			Logger.LogDebug((object)("Bear can consume " + ((Object)val).name));
		}
	}

	private void SetRandomStartingNames(Tameable tameable)
	{
		tameable.m_randomStartingName = new List<string>();
		for (int i = 0; i < randomNameCount; i++)
		{
			tameable.m_randomStartingName.Add(string.Format("${0}{1}", "name_randBearName", i));
		}
	}

	private EffectData DuplicateEffectData(EffectData fxData)
	{
		//IL_004b: 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_0057: Unknown result type (might be due to invalid IL or missing references)
		//IL_0063: Unknown result type (might be due to invalid IL or missing references)
		//IL_006f: Unknown result type (might be due to invalid IL or missing references)
		//IL_007b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0087: Unknown result type (might be due to invalid IL or missing references)
		//IL_0093: Unknown result type (might be due to invalid IL or missing references)
		//IL_009f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ab: 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)
		//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d0: Expected O, but got Unknown
		if ((Object)(object)fxData.m_prefab == (Object)null)
		{
			return null;
		}
		GameObject prefab = PrefabManager.Instance.GetPrefab(((Object)fxData.m_prefab).name);
		if ((Object)(object)prefab == (Object)null)
		{
			Logger.LogWarning((object)("Could not get effect prefab " + ((Object)fxData.m_prefab).name));
			return null;
		}
		return new EffectData
		{
			m_prefab = prefab,
			m_enabled = fxData.m_enabled,
			m_variant = fxData.m_variant,
			m_attach = fxData.m_attach,
			m_follow = fxData.m_follow,
			m_inheritParentRotation = fxData.m_inheritParentRotation,
			m_inheritParentScale = fxData.m_inheritParentScale,
			m_multiplyParentVisualScale = fxData.m_multiplyParentVisualScale,
			m_randomRotation = fxData.m_randomRotation,
			m_scale = fxData.m_scale,
			m_childTransform = fxData.m_childTransform
		};
	}

	[IteratorStateMachine(typeof(<EnumerateConsumables>d__22))]
	private IEnumerable<string> EnumerateConsumables(ConfigEntry<string> configConsumables)
	{
		//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
		return new <EnumerateConsumables>d__22(-2)
		{
			<>3__configConsumables = configConsumables
		};
	}

	private void ResolveLocalizations()
	{
		try
		{
			DirectoryInfo directoryInfo = new DirectoryInfo(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location));
			Dictionary<string, List<FileInfo>> dictionary = new Dictionary<string, List<FileInfo>>();
			foreach (FileInfo item in directoryInfo.EnumerateFiles("*.json", SearchOption.TopDirectoryOnly))
			{
				string[] array = item.Name.Split(new char[1] { '.' }, StringSplitOptions.RemoveEmptyEntries);
				if (array.Length <= 2 || !(array.Last() == "json"))
				{
					continue;
				}
				string text = array[^2].Trim();
				if (LocalizationHelper.IsLanguageSupported(text))
				{
					if (!dictionary.ContainsKey(text))
					{
						dictionary.Add(text, new List<FileInfo>());
					}
					dictionary[text].Add(item);
				}
			}
			foreach (string key in dictionary.Keys)
			{
				if (Localization.GetLanguages().Contains(key))
				{
					continue;
				}
				foreach (FileInfo item2 in dictionary[key])
				{
					Localization.AddJsonFile(key, File.ReadAllText(item2.FullName));
					((BaseUnityPlugin)this).Logger.LogInfo((object)("Added localization file [" + item2.Name + "] from non-standard location."));
				}
			}
			foreach (string language in Localization.GetLanguages())
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)(language + " localization loaded and available."));
			}
		}
		catch (Exception)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"Error resolving localizations.");
		}
	}
}