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.");
}
}
}