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 TameBond v0.1.1
TameBond.dll
Decompiled a day agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using Jotunn.Utils; 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("TameBond")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.1.1.0")] [assembly: AssemblyInformationalVersion("0.1.1+dec535b5570b4eea66988bb670f68342c2ac7f4c")] [assembly: AssemblyProduct("TameBond")] [assembly: AssemblyTitle("TameBond")] [assembly: AssemblyVersion("0.1.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 TameBond { public sealed class SpeciesList { public readonly IReadOnlyList<string> Names; private SpeciesList(List<string> names) { Names = names; } public static SpeciesList Parse(string csv) { List<string> list = new List<string>(); string[] array = (csv ?? "").Split(','); for (int i = 0; i < array.Length; i++) { string text = array[i].Trim(); if (text.Length > 0 && !list.Contains(text)) { list.Add(text); } } return new SpeciesList(list); } public string Of(string prefabName) { if (string.IsNullOrEmpty(prefabName)) { return null; } foreach (string name in Names) { if (prefabName == name) { return name; } } return null; } } public sealed class YoungMap { private readonly Dictionary<string, string> map = new Dictionary<string, string>(); public int Count => map.Count; public static YoungMap Parse(string csv, out string error) { error = null; YoungMap youngMap = new YoungMap(); string[] array = (csv ?? "").Split(','); for (int i = 0; i < array.Length; i++) { string text = array[i].Trim(); if (text.Length != 0) { string[] array2 = text.Split(':'); if (array2.Length != 2 || array2[0].Trim().Length == 0 || array2[1].Trim().Length == 0) { error = "bad young entry '" + text + "', expected YoungPrefab:Species"; return new YoungMap(); } youngMap.map[array2[0].Trim()] = array2[1].Trim(); } } return youngMap; } public string SpeciesOf(string prefabName) { if (prefabName == null || !map.TryGetValue(prefabName, out var value)) { return null; } return value; } } public static class BondStore { public const string KeyPrefix = "syxe.TameBond."; public static string Key(string world) { return "syxe.TameBond." + world; } public static List<string> Read(IDictionary<string, string> data, string world) { List<string> list = new List<string>(); if (data != null && data.TryGetValue(Key(world), out var value)) { string[] array = value.Split(','); foreach (string text in array) { if (text.Length > 0 && !list.Contains(text)) { list.Add(text); } } } return list; } public static bool Has(IDictionary<string, string> data, string world, string species) { return Read(data, world).Contains(species); } public static bool Add(IDictionary<string, string> data, string world, string species) { List<string> list = Read(data, world); if (list.Contains(species)) { return false; } list.Add(species); data[Key(world)] = string.Join(",", list); return true; } } public struct Requirement { public string Item; public int Amount; } public static class Requirements { public static List<Requirement> Parse(string csv, out string error) { error = null; List<Requirement> list = new List<Requirement>(); string[] array = (csv ?? "").Split(','); for (int i = 0; i < array.Length; i++) { string text = array[i].Trim(); if (text.Length != 0) { string[] array2 = text.Split(':'); if (array2.Length != 2 || array2[0].Trim().Length == 0 || !int.TryParse(array2[1].Trim(), out var result) || result < 1) { error = "bad requirement '" + text + "', expected Item:Amount"; return new List<Requirement>(); } list.Add(new Requirement { Item = array2[0].Trim(), Amount = result }); } } return list; } } public sealed class StoneSpec { public string Model; public string Tint; public List<Requirement> Cost; public static StoneSpec Parse(string line, out string error) { error = null; string[] array = (line ?? "").Split('|'); StoneSpec stoneSpec = new StoneSpec { Model = array[0].Trim(), Tint = ((array.Length > 1) ? array[1].Trim() : ""), Cost = new List<Requirement>() }; if (stoneSpec.Model.Length == 0) { return stoneSpec; } if (array.Length > 3) { error = "expected model | tint | cost"; return stoneSpec; } if (stoneSpec.Tint.Length > 0 && !TryParseTint(stoneSpec.Tint, out var _, out var _, out var _)) { error = "bad tint '" + stoneSpec.Tint + "', expected #rrggbb"; return stoneSpec; } stoneSpec.Cost = Requirements.Parse((array.Length > 2) ? array[2] : "", out error); return stoneSpec; } public static bool TryParseTint(string hex, out float r, out float g, out float b) { r = (g = (b = 0f)); if (hex == null || hex.Length != 7 || hex[0] != '#') { return false; } if (!int.TryParse(hex.Substring(1), NumberStyles.HexNumber, null, out var result)) { return false; } r = (float)((result >> 16) & 0xFF) / 255f; g = (float)((result >> 8) & 0xFF) / 255f; b = (float)(result & 0xFF) / 255f; return true; } } public class BondStone : MonoBehaviour, Interactable, Hoverable { public string m_species = ""; public string m_label = ""; public string GetHoverText() { return Localization.instance.Localize(m_label + "\n[<color=yellow><b>$KEY_Use</b></color>] $tamebond_use" + (Plugin.StonesSacrifice.Value ? "\n<color=orange>$tamebond_takes_life</color>" : "") + Unlock.BondedLine(Player.m_localPlayer)); } public string GetHoverName() { return Localization.instance.Localize(m_label); } public float GetHoverOffset() { return 0f; } public bool Interact(Humanoid user, bool hold, bool alt) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) if (!hold) { Player val = (Player)(object)((user is Player) ? user : null); if (val != null) { if (!Plugin.StonesEnabled.Value) { ((Character)val).Message((MessageType)2, Localization.instance.Localize("$tamebond_stone_off"), 0, (Sprite)null, false); } else { Unlock.Perform(val, ((Component)this).transform.position, Plugin.StonesSacrifice.Value, m_species); } return true; } } return false; } public bool UseItem(Humanoid user, ItemData item) { return false; } } internal static class StonePiece { private static readonly Dictionary<string, GameObject> prefabs = new Dictionary<string, GameObject>(); private static bool attempted; internal static void Register() { if (attempted) { return; } attempted = true; foreach (KeyValuePair<string, ConfigEntry<string>> stoneLine in Plugin.StoneLines) { try { Build(stoneLine.Key, stoneLine.Value.Value); } catch (Exception ex) { Plugin.Log.LogError((object)(stoneLine.Key + " stone not registered: " + ex)); } } } private static void Build(string species, string line) { //IL_0212: Unknown result type (might be due to invalid IL or missing references) //IL_0217: Unknown result type (might be due to invalid IL or missing references) //IL_021f: Unknown result type (might be due to invalid IL or missing references) //IL_022c: Unknown result type (might be due to invalid IL or missing references) //IL_0237: Unknown result type (might be due to invalid IL or missing references) //IL_0242: Unknown result type (might be due to invalid IL or missing references) //IL_024f: Unknown result type (might be due to invalid IL or missing references) //IL_025f: Unknown result type (might be due to invalid IL or missing references) //IL_026d: Expected O, but got Unknown //IL_0299: Unknown result type (might be due to invalid IL or missing references) //IL_02a3: Expected O, but got Unknown //IL_0208: Unknown result type (might be due to invalid IL or missing references) string error; StoneSpec stoneSpec = StoneSpec.Parse(line, out error); if (error != null) { Plugin.Log.LogError((object)("Stones." + species + " ignored: " + error)); } else { if (stoneSpec.Model.Length == 0) { return; } GameObject prefab = PrefabManager.Instance.GetPrefab(stoneSpec.Model); if ((Object)(object)prefab == (Object)null) { Plugin.Log.LogError((object)("Stones." + species + ": no vanilla prefab " + stoneSpec.Model + ", stone not registered")); return; } string text = "TameBond_" + species; GameObject val = PrefabManager.Instance.CreateClonedPrefab(text, prefab); if ((Object)(object)val == (Object)null) { Plugin.Log.LogError((object)("Stones." + species + ": clone of " + stoneSpec.Model + " failed")); return; } Strip(val); (val.GetComponent<ZNetView>() ?? val.AddComponent<ZNetView>()).m_persistent = true; Piece val2 = val.GetComponent<Piece>() ?? val.AddComponent<Piece>(); GameObject prefab2 = PrefabManager.Instance.GetPrefab(species); Character val3 = (((Object)(object)prefab2 != (Object)null) ? prefab2.GetComponent<Character>() : null); string text2 = (val2.m_name = (((Object)(object)val3 != (Object)null && !string.IsNullOrEmpty(val3.m_name)) ? val3.m_name : species) + " $tamebond_stone"); val2.m_description = "$tamebond_stone_desc"; val2.m_canBeRemoved = true; val2.m_enabled = Plugin.StonesEnabled.Value; if ((Object)(object)val.GetComponent<WearNTear>() == (Object)null) { WearNTear obj = val.AddComponent<WearNTear>(); obj.m_health = 500f; obj.m_noRoofWear = true; obj.m_noSupportWear = true; } BondStone bondStone = val.AddComponent<BondStone>(); bondStone.m_species = species; bondStone.m_label = text2; if (stoneSpec.Tint.Length > 0 && StoneSpec.TryParseTint(stoneSpec.Tint, out var r, out var g, out var b)) { Tint(val, new Color(r, g, b)); } PieceConfig val4 = new PieceConfig { Name = text2, Description = val2.m_description, PieceTable = PieceTables.Hammer, Category = PieceCategories.Misc, Icon = val2.m_icon, Enabled = Plugin.StonesEnabled.Value, Requirements = Cost(stoneSpec) }; if (!string.IsNullOrEmpty(Plugin.StoneStation.Value)) { val4.CraftingStation = Plugin.StoneStation.Value; } if (!PieceManager.Instance.AddPiece(new CustomPiece(val, false, val4))) { Plugin.Log.LogError((object)("Jotunn refused the " + species + " stone")); return; } prefabs[species] = val; Plugin.Log.LogInfo((object)(species + " stone registered from " + stoneSpec.Model + ", cost " + line)); } } private static void Strip(GameObject prefab) { MonoBehaviour[] componentsInChildren = prefab.GetComponentsInChildren<MonoBehaviour>(true); foreach (MonoBehaviour val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && !(val is Piece) && !(val is WearNTear) && !(val is ZNetView) && !(val is ZSyncTransform) && (val is Interactable || val is Hoverable || val is Fireplace || val is Beehive || val is Chair || val is Container || val is Sign || val is Bed || val is Switch)) { Object.DestroyImmediate((Object)(object)val); } } } private static void Tint(GameObject prefab, Color c) { //IL_0048: 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_0075: Unknown result type (might be due to invalid IL or missing references) Renderer[] componentsInChildren = prefab.GetComponentsInChildren<Renderer>(true); foreach (Renderer val in componentsInChildren) { Material[] materials = val.materials; Material[] array = materials; foreach (Material val2 in array) { if (!((Object)(object)val2 == (Object)null)) { if (val2.HasProperty("_Color")) { val2.SetColor("_Color", c); } if (val2.HasProperty("_EmissionColor")) { val2.EnableKeyword("_EMISSION"); val2.SetColor("_EmissionColor", c * 0.3f); } } } val.materials = materials; } } private static RequirementConfig[] Cost(StoneSpec spec) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown List<RequirementConfig> list = new List<RequirementConfig>(); foreach (Requirement item in spec.Cost) { list.Add(new RequirementConfig(item.Item, item.Amount, 0, Plugin.RefundOnRemove.Value)); } return list.ToArray(); } internal static string PlacementRefusal(Player player) { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) if (!Plugin.StonesEnabled.Value) { return "$tamebond_stone_off"; } if (Plugin.BedDistance.Value <= 0f) { return null; } PlayerProfile val = (((Object)(object)Game.instance != (Object)null) ? Game.instance.GetPlayerProfile() : null); if (val == null || !val.HaveCustomSpawnPoint()) { return "$tamebond_no_bed"; } if (!(Vector3.Distance(val.GetCustomSpawnPoint(), ((Component)player).transform.position) <= Plugin.BedDistance.Value)) { return "$tamebond_far_from_bed"; } return null; } internal static void ApplyEnabled() { foreach (KeyValuePair<string, GameObject> prefab in prefabs) { Piece component = prefab.Value.GetComponent<Piece>(); if ((Object)(object)component != (Object)null) { component.m_enabled = Plugin.StonesEnabled.Value; } } Plugin.Log.LogInfo((object)("bond stones " + (Plugin.StonesEnabled.Value ? "enabled" : "disabled"))); } internal static void ApplyCost(string species) { //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Expected O, but got Unknown if (!prefabs.TryGetValue(species, out var value) || (Object)(object)ObjectDB.instance == (Object)null) { return; } Piece component = value.GetComponent<Piece>(); string error; StoneSpec stoneSpec = StoneSpec.Parse(Plugin.StoneLines[species].Value, out error); if ((Object)(object)component == (Object)null) { return; } if (error != null) { Plugin.Log.LogError((object)("Stones." + species + " ignored: " + error)); return; } List<Requirement> list = new List<Requirement>(); foreach (Requirement item in stoneSpec.Cost) { GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(item.Item); ItemDrop val = (((Object)(object)itemPrefab != (Object)null) ? itemPrefab.GetComponent<ItemDrop>() : null); if ((Object)(object)val == (Object)null) { Plugin.Log.LogError((object)("Stones." + species + " ignored: no item " + item.Item)); return; } list.Add(new Requirement { m_resItem = val, m_amount = item.Amount, m_recover = Plugin.RefundOnRemove.Value }); } component.m_resources = list.ToArray(); Plugin.Log.LogInfo((object)(species + " stone cost now " + Plugin.StoneLines[species].Value)); } } [HarmonyPatch(typeof(Vegvisir), "Interact")] internal static class VegvisirInteract { private static bool Prefix(Vegvisir __instance, Humanoid character, bool hold, bool alt) { //IL_004a: Unknown result type (might be due to invalid IL or missing references) if (!(!alt || hold) && Plugin.VegvisirEnabled.Value) { Player val = (Player)(object)((character is Player) ? character : null); if (val != null) { if (!SpawnStone.Is(__instance)) { ((Character)val).Message((MessageType)2, Localization.instance.Localize("$tamebond_not_spawn"), 0, (Sprite)null, false); } else { Unlock.Perform(val, ((Component)__instance).transform.position, Plugin.VegvisirSacrifice.Value); } return false; } } return true; } } [HarmonyPatch(typeof(Vegvisir), "GetHoverText")] internal static class VegvisirHover { private static void Postfix(Vegvisir __instance, ref string __result) { if (Plugin.VegvisirEnabled.Value && SpawnStone.Is(__instance)) { __result += Localization.instance.Localize("\n[<color=yellow><b>$KEY_AltPlace + $KEY_Use</b></color>] $tamebond_use" + (Plugin.VegvisirSacrifice.Value ? "\n<color=orange>$tamebond_takes_life</color>" : "") + Unlock.BondedLine(Player.m_localPlayer)); } } } internal static class SpawnStone { private static readonly Dictionary<Vector3, string> icons = new Dictionary<Vector3, string>(); internal static bool Is(Vegvisir v) { //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) if (!Plugin.VegvisirSpawnOnly.Value) { return true; } if ((Object)(object)ZoneSystem.instance == (Object)null) { return false; } icons.Clear(); ZoneSystem.instance.GetLocationIcons(icons); foreach (KeyValuePair<Vector3, string> icon in icons) { if (icon.Value == "StartTemple" && Vector3.Distance(icon.Key, ((Component)v).transform.position) <= Plugin.SpawnDistance.Value) { return true; } } return false; } } [HarmonyPatch(typeof(Player), "TryPlacePiece")] internal static class PlaceBondStone { private static bool Prefix(Player __instance, Piece piece, ref bool __result) { if ((Object)(object)piece == (Object)null || (Object)(object)((Component)piece).GetComponent<BondStone>() == (Object)null) { return true; } string text = StonePiece.PlacementRefusal(__instance); if (text == null) { return true; } ((Character)__instance).Message((MessageType)2, Localization.instance.Localize(text), 0, (Sprite)null, false); __result = false; return false; } } [HarmonyPatch] internal static class TeleportCreaturesGate { private const string TypeName = "TeleportCreatures.EffectiveCreaturePolicy"; private static MethodBase target; private static bool Prepare(MethodBase original) { if (original != null) { return true; } bool flag = Chainloader.PluginInfos.ContainsKey("odinplus.TeleportCreatures"); Type type = AccessTools.TypeByName("TeleportCreatures.EffectiveCreaturePolicy"); if (type == null) { if (flag) { Plugin.Log.LogError((object)"TeleportCreatures is loaded but TeleportCreatures.EffectiveCreaturePolicy is missing: the bond gate is OFF, tames travel ungated"); } else { Plugin.Log.LogWarning((object)"TeleportCreatures not loaded: bond gate not installed"); } return false; } target = AccessTools.FirstMethod(type, (Func<MethodInfo, bool>)delegate(MethodInfo m) { if (m.Name != "IsAllowed" || m.IsStatic || m.ReturnType != typeof(bool)) { return false; } ParameterInfo[] parameters = m.GetParameters(); return parameters.Length == 5 && parameters[0].ParameterType == typeof(string) && parameters[0].Name == "prefabName" && parameters[1].ParameterType == typeof(bool) && parameters[1].Name == "isTamed" && parameters[2].ParameterType == typeof(bool) && parameters[3].ParameterType == typeof(bool); }); if (target == null) { Plugin.Log.LogError((object)"TeleportCreatures.EffectiveCreaturePolicy.IsAllowed(string prefabName, bool isTamed, bool, bool, PortalContext) not found: the bond gate is OFF, tames travel ungated. Pin TeleportCreatures or update TameBond."); return false; } Plugin.Log.LogInfo((object)("bond gate on TeleportCreatures.EffectiveCreaturePolicy." + target.Name)); return true; } private static MethodBase TargetMethod() { return target; } private static void Postfix(ref bool __result, string prefabName, bool isTamed) { if (__result && isTamed) { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null) && !Unlock.Allows(localPlayer, prefabName)) { __result = false; } } } } [BepInPlugin("syxe.TameBond", "TameBond", "0.1.1")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { public enum UnlistedRule { Free, Blocked } public const string Guid = "syxe.TameBond"; public const string Name = "TameBond"; public const string Version = "0.1.1"; public const string TeleportCreaturesGuid = "odinplus.TeleportCreatures"; internal static ManualLogSource Log; internal static SpeciesList Species = SpeciesList.Parse(""); internal static YoungMap Young = YoungMap.Parse("", out var _); internal static ConfigEntry<string> SpeciesCfg; internal static ConfigEntry<UnlistedRule> Unlisted; internal static ConfigEntry<string> YoungCfg; internal static ConfigEntry<bool> YoungTravel; internal static ConfigEntry<float> UnlockRadius; internal static ConfigEntry<bool> VegvisirEnabled; internal static ConfigEntry<bool> VegvisirSpawnOnly; internal static ConfigEntry<float> SpawnDistance; internal static ConfigEntry<bool> VegvisirSacrifice; internal static ConfigEntry<bool> StonesSacrifice; internal static ConfigEntry<bool> StonesEnabled; internal static ConfigEntry<float> BedDistance; internal static ConfigEntry<bool> RefundOnRemove; internal static ConfigEntry<string> StoneStation; internal static readonly Dictionary<string, ConfigEntry<string>> StoneLines = new Dictionary<string, ConfigEntry<string>>(); private static readonly Dictionary<string, string> DefaultStones = new Dictionary<string, string> { ["Boar"] = "piece_beehive | #D9A441 | DeerHide:20,Bronze:5,TrophyBoar:3", ["Wolf"] = "darkwood_wolf | #8FC7FF | WolfPelt:20,Silver:5,TrophyWolf:3", ["Lox"] = "darkwood_raven | #E0B050 | LoxPelt:20,BlackMetal:5,TrophyLox:3", ["Asksvin"] = "piece_wisplure | #FF7A30 | ScaleHide:20,FlametalNew:5,TrophyAsksvin:3", ["Moose"] = "piece_moose_throne | #7FE0C8 | MooseHide:20,Gold:5,TrophyMoose:3" }; private Harmony harmony; private void Awake() { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Expected O, but got Unknown //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Expected O, but got Unknown //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Expected O, but got Unknown //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Expected O, but got Unknown //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Expected O, but got Unknown //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Expected O, but got Unknown //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Expected O, but got Unknown //IL_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_01bf: Expected O, but got Unknown //IL_01e5: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Expected O, but got Unknown //IL_0215: Unknown result type (might be due to invalid IL or missing references) //IL_021f: Expected O, but got Unknown //IL_0245: Unknown result type (might be due to invalid IL or missing references) //IL_024f: Expected O, but got Unknown //IL_0287: Unknown result type (might be due to invalid IL or missing references) //IL_0291: Expected O, but got Unknown //IL_02b7: Unknown result type (might be due to invalid IL or missing references) //IL_02c1: Expected O, but got Unknown //IL_02eb: Unknown result type (might be due to invalid IL or missing references) //IL_02f5: Expected O, but got Unknown //IL_035f: Unknown result type (might be due to invalid IL or missing references) //IL_0369: Expected O, but got Unknown //IL_0547: Unknown result type (might be due to invalid IL or missing references) //IL_0573: Unknown result type (might be due to invalid IL or missing references) //IL_057d: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; ConfigurationManagerAttributes val = new ConfigurationManagerAttributes { IsAdminOnly = true }; SpeciesCfg = ((BaseUnityPlugin)this).Config.Bind<string>("Species", "List", "Boar,Wolf,Lox,Asksvin,Moose", new ConfigDescription("Prefab names of the species that need a bond before they follow through a portal. A species added here gets its Stones line at the next game start.", (AcceptableValueBase)null, new object[1] { val })); YoungCfg = ((BaseUnityPlugin)this).Config.Bind<string>("Species", "Young", "Boar_piggy:Boar,Wolf_cub:Wolf,Lox_Calf:Lox,Asksvin_hatchling:Asksvin,Moose_calf:Moose", new ConfigDescription("Juvenile prefab to species, as YoungPrefab:Species pairs. Young never count for a bond; whether they travel is YoungTravel.", (AcceptableValueBase)null, new object[1] { val })); YoungTravel = ((BaseUnityPlugin)this).Config.Bind<bool>("Species", "YoungTravel", false, new ConfigDescription("Let a listed young animal follow a player who holds its species' bond. Off, young never go through a portal.", (AcceptableValueBase)null, new object[1] { val })); Unlisted = ((BaseUnityPlugin)this).Config.Bind<UnlistedRule>("Species", "UnlistedSpecies", UnlistedRule.Blocked, new ConfigDescription("Species not in the list: Free leaves them to TeleportCreatures' own policy, Blocked never lets them through.", (AcceptableValueBase)null, new object[1] { val })); UnlockRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Unlock", "Radius", 10f, new ConfigDescription("Metres around the stone within which a tame counts for the bond.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 50f), new object[1] { val })); VegvisirEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Vegvisir", "Enabled", true, new ConfigDescription("Shift + Use on a Vegvisir bonds every listed species in range. Plain Use keeps its vanilla job.", (AcceptableValueBase)null, new object[1] { val })); VegvisirSpawnOnly = ((BaseUnityPlugin)this).Config.Bind<bool>("Vegvisir", "SpawnOnly", true, new ConfigDescription("Only the Vegvisir at the start temple bonds; other boss stones refuse.", (AcceptableValueBase)null, new object[1] { val })); SpawnDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Vegvisir", "SpawnDistance", 100f, new ConfigDescription("Metres from the StartTemple location within which a Vegvisir counts as the spawn stone.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 500f), new object[1] { val })); VegvisirSacrifice = ((BaseUnityPlugin)this).Config.Bind<bool>("Vegvisir", "Sacrifice", true, new ConfigDescription("Bonding at the Vegvisir kills the animal bonded (one per kind), so each player brings their own.", (AcceptableValueBase)null, new object[1] { val })); StonesSacrifice = ((BaseUnityPlugin)this).Config.Bind<bool>("Stones", "Sacrifice", true, new ConfigDescription("Bonding at a bond stone kills the animal bonded.", (AcceptableValueBase)null, new object[1] { val })); StonesEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Stones", "Enabled", false, new ConfigDescription("Offer the per-species bond stones in the hammer and let placed stones bond. Off (the default), only the spawn Vegvisir bonds.", (AcceptableValueBase)null, new object[1] { val })); BedDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Stones", "BedDistance", 50f, new ConfigDescription("A stone can only be placed this close to the placer's own bed (spawn point); 0 lifts the rule.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 500f), new object[1] { val })); RefundOnRemove = ((BaseUnityPlugin)this).Config.Bind<bool>("Stones", "RefundOnRemove", false, new ConfigDescription("Give the materials back when a stone is picked up with the hammer. Read at game start.", (AcceptableValueBase)null, new object[1] { val })); StoneStation = ((BaseUnityPlugin)this).Config.Bind<string>("Stones", "CraftingStation", "piece_workbench", new ConfigDescription("Crafting station a stone needs nearby; empty for none. Read at game start.", (AcceptableValueBase)null, new object[1] { val })); foreach (string name in SpeciesList.Parse(SpeciesCfg.Value).Names) { DefaultStones.TryGetValue(name, out var value); StoneLines[name] = ((BaseUnityPlugin)this).Config.Bind<string>("Stones", name, value ?? "", new ConfigDescription("This species' stone as 'model | #rrggbb tint | Item:Amount,...': a vanilla buildable to clone, a tint for its materials, the build cost. Empty: no stone. Model and tint are read at game start, the cost applies live.", (AcceptableValueBase)null, new object[1] { val })); string s = name; StoneLines[name].SettingChanged += delegate { StonePiece.ApplyCost(s); }; } Species = SpeciesList.Parse(SpeciesCfg.Value); SpeciesCfg.SettingChanged += delegate { Species = SpeciesList.Parse(SpeciesCfg.Value); }; LoadYoung(); YoungCfg.SettingChanged += delegate { LoadYoung(); }; StonesEnabled.SettingChanged += delegate { StonePiece.ApplyEnabled(); }; CustomLocalization localization = LocalizationManager.Instance.GetLocalization(); string text = "English"; localization.AddTranslation(ref text, new Dictionary<string, string> { ["tamebond_stone"] = "bond stone", ["tamebond_stone_desc"] = "Bring one of them here and use the stone: that kind may then follow you through portals.", ["tamebond_use"] = "Bond tames in range", ["tamebond_bonded"] = "Bonded with", ["tamebond_given"] = "the animal is given to the stone", ["tamebond_takes_life"] = "Bonding takes the animal's life", ["tamebond_already"] = "Already bonded with", ["tamebond_none"] = "No tame of a bondable kind is near the stone", ["tamebond_not_spawn"] = "Only the stone at the start temple binds tames", ["tamebond_no_world"] = "Not in a world", ["tamebond_bonded_here"] = "Bonded here", ["tamebond_stone_off"] = "Bond stones are not in use on this server", ["tamebond_no_bed"] = "A bond stone stands near your bed; claim one first", ["tamebond_far_from_bed"] = "Too far from your bed for a bond stone" }); new ConfigFileWatcher(((BaseUnityPlugin)this).Config, 1000L); PrefabManager.OnVanillaPrefabsAvailable += StonePiece.Register; harmony = new Harmony("syxe.TameBond"); harmony.PatchAll(typeof(Plugin).Assembly); if (Chainloader.PluginInfos.TryGetValue("odinplus.TeleportCreatures", out var value2)) { Log.LogInfo((object)("TameBond 0.1.1 with TeleportCreatures " + value2.Metadata.Version)); } else { Log.LogWarning((object)"TameBond 0.1.1: TeleportCreatures is not loaded, so nothing transports tames; bonds are still recorded"); } } private static void LoadYoung() { Young = YoungMap.Parse(YoungCfg.Value, out var error); if (error != null) { Log.LogError((object)("Species.Young ignored: " + error)); } } internal static string WorldKey() { string text = (((Object)(object)ZNet.instance != (Object)null) ? ZNet.instance.GetWorldName() : null); if (!string.IsNullOrEmpty(text)) { return text; } return null; } } internal static class Unlock { internal static Dictionary<string, Character> SpeciesNear(Vector3 point, float radius, string only = null) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) Dictionary<string, Character> dictionary = new Dictionary<string, Character>(); foreach (Character allCharacter in Character.GetAllCharacters()) { if ((Object)(object)allCharacter == (Object)null || !allCharacter.IsTamed() || allCharacter.IsDead()) { continue; } float num = Vector3.Distance(((Component)allCharacter).transform.position, point); if (!(num > radius)) { string text = Plugin.Species.Of(Utils.GetPrefabName(((Component)allCharacter).gameObject)); if (text != null && (only == null || !(text != only)) && (!dictionary.TryGetValue(text, out var value) || num < Vector3.Distance(((Component)value).transform.position, point))) { dictionary[text] = allCharacter; } } } return dictionary; } internal static void Perform(Player player, Vector3 point, bool sacrifice, string only = null) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) string text = Plugin.WorldKey(); if (text == null) { Say(player, "$tamebond_no_world"); return; } Dictionary<string, Character> dictionary = SpeciesNear(point, Plugin.UnlockRadius.Value, only); if (dictionary.Count == 0) { Say(player, "$tamebond_none"); return; } List<string> list = new List<string>(); List<string> list2 = new List<string>(); foreach (KeyValuePair<string, Character> item in dictionary) { if (!BondStore.Add(player.m_customData, text, item.Key)) { list2.Add(item.Value.m_name); continue; } list.Add(item.Value.m_name); if (sacrifice) { Kill(item.Value); } } if (list.Count > 0) { Say(player, "$tamebond_bonded " + string.Join(", ", list) + (sacrifice ? "; $tamebond_given" : "")); Plugin.Log.LogInfo((object)("bonded " + player.GetPlayerName() + " in " + text + " with " + string.Join(",", list) + (sacrifice ? ", sacrificed" : ""))); } else { Say(player, "$tamebond_already " + string.Join(", ", list2)); } } private static void Kill(Character c) { ZNetView component = ((Component)c).GetComponent<ZNetView>(); if (!((Object)(object)component == (Object)null) && component.IsValid()) { if (!component.IsOwner()) { component.ClaimOwnership(); } c.SetHealth(0f); } } internal static bool Allows(Player player, string prefabName) { string text = Plugin.Young.SpeciesOf(prefabName); if (text != null && !Plugin.YoungTravel.Value) { return false; } string text2 = text ?? Plugin.Species.Of(prefabName); if (text2 == null) { return Plugin.Unlisted.Value == Plugin.UnlistedRule.Free; } string text3 = Plugin.WorldKey(); if (text3 != null) { return BondStore.Has(player.m_customData, text3, text2); } return false; } internal static string BondedLine(Player player) { string text = Plugin.WorldKey(); if ((Object)(object)player == (Object)null || text == null) { return ""; } List<string> list = BondStore.Read(player.m_customData, text); if (list.Count != 0) { return "\n$tamebond_bonded_here: " + string.Join(", ", list); } return ""; } private static void Say(Player player, string text) { ((Character)player).Message((MessageType)2, Localization.instance.Localize(text), 0, (Sprite)null, false); } } }