Decompiled source of ImprovedTames v0.1.3

ImprovedTames.dll

Decompiled 4 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
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 ImprovedTames.Logic;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("0.0.0.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 ImprovedTames
{
	internal static class ImprovedTamesConfig
	{
		public static ConfigEntry<bool> Enabled;

		public static ConfigEntry<float> MaxDistance;

		public static ConfigEntry<float> ArrivalRadius;

		public static ConfigEntry<bool> DebugLogging;

		public static void Bind(ConfigFile config)
		{
			Enabled = config.Bind<bool>("1 - Portal teleport", "Enabled", true, AdminOnly("Tames following you go through portals with you."));
			MaxDistance = config.Bind<float>("1 - Portal teleport", "MaxDistance", 50f, AdminOnly("How far from the portal (metres) a following tame can be and still come along.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 128f)));
			ArrivalRadius = config.Bind<float>("1 - Portal teleport", "ArrivalRadius", 4f, AdminOnly("How far from you (metres) tames appear after the teleport.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 15f)));
			DebugLogging = config.Bind<bool>("9 - Debug", "DebugLogging", false, "Log every tame moved through a portal (local only).");
		}

		private static ConfigDescription AdminOnly(string description, AcceptableValueBase range = null)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected O, but got Unknown
			return new ConfigDescription(description, range, new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			} });
		}
	}
	[BepInPlugin("com.robert.improvedtames", "ImprovedTames", "0.1.3")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	public class ImprovedTamesPlugin : BaseUnityPlugin
	{
		internal static ManualLogSource Log;

		internal static TameTeleporter Teleporter;

		private Harmony _harmony;

		private void Awake()
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			ImprovedTamesConfig.Bind(((BaseUnityPlugin)this).Config);
			Teleporter = new TameTeleporter((MonoBehaviour)(object)this);
			_harmony = new Harmony("com.robert.improvedtames");
			_harmony.PatchAll(typeof(ImprovedTamesPlugin).Assembly);
		}

		private void OnDestroy()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}
	}
	[HarmonyPatch]
	internal static class PotalMapTeleportPatch
	{
		public const string PotalMapGuid = "com.korcaptain.potalmap";

		private static MethodBase Target()
		{
			return AccessTools.Method("PortalMap.PortalTeleporter:TryTeleport", (Type[])null, (Type[])null);
		}

		private static bool Prepare()
		{
			if (!Chainloader.PluginInfos.ContainsKey("com.korcaptain.potalmap"))
			{
				return false;
			}
			if (Target() == null)
			{
				ImprovedTamesPlugin.Log.LogWarning((object)"PotalMap's TryTeleport was not found, so tames won't follow its teleports.");
				return false;
			}
			return true;
		}

		private static MethodBase TargetMethod()
		{
			return Target();
		}

		private static void Prefix(out bool __state)
		{
			Player localPlayer = Player.m_localPlayer;
			__state = (Object)(object)localPlayer != (Object)null && ((Character)localPlayer).IsTeleporting();
		}

		private static void Postfix(bool __state)
		{
			Player localPlayer = Player.m_localPlayer;
			if (!__state && (Object)(object)localPlayer != (Object)null && ((Character)localPlayer).IsTeleporting())
			{
				ImprovedTamesPlugin.Teleporter.OnPortalEntered(localPlayer);
			}
		}
	}
	internal sealed class TameTeleporter
	{
		private const float ArrivalTimeout = 40f;

		private const int PlaceAttempts = 3;

		private const float RetryDelay = 2f;

		private const float ArrivedDistance = 15f;

		private const float MaxFloorDifference = 3f;

		private const float SpawnLift = 0.5f;

		private readonly MonoBehaviour _host;

		private Coroutine _running;

		public TameTeleporter(MonoBehaviour host)
		{
			_host = host;
		}

		public void OnPortalEntered(Player player)
		{
			if (!ImprovedTamesConfig.Enabled.Value)
			{
				return;
			}
			List<ZDOID> list = ClaimFollowers(player);
			if (list.Count != 0)
			{
				if (_running != null)
				{
					_host.StopCoroutine(_running);
				}
				_running = _host.StartCoroutine(BringAfterArrival(player, list));
			}
		}

		private static List<ZDOID> ClaimFollowers(Player player)
		{
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			List<ZDOID> list = new List<ZDOID>();
			string playerName = player.GetPlayerName();
			float value = ImprovedTamesConfig.MaxDistance.Value;
			foreach (Character allCharacter in Character.GetAllCharacters())
			{
				if (allCharacter.IsPlayer() || !allCharacter.IsTamed())
				{
					continue;
				}
				Tameable component = ((Component)allCharacter).GetComponent<Tameable>();
				if (!((Object)(object)component == (Object)null) && !(component.m_unsummonDistance > 0f) && !component.HaveRider())
				{
					ZNetView component2 = ((Component)allCharacter).GetComponent<ZNetView>();
					if (!((Object)(object)component2 == (Object)null) && component2.IsValid() && FollowerRules.IsFollowing(component2.GetZDO().GetString(ZDOVars.s_follow, ""), playerName) && !(Vector3.Distance(((Component)allCharacter).transform.position, ((Component)player).transform.position) > value))
					{
						component2.ClaimOwnership();
						list.Add(allCharacter.GetZDOID());
					}
				}
			}
			return list;
		}

		private static IEnumerator BringAfterArrival(Player player, List<ZDOID> followers)
		{
			float waited = 0f;
			while ((Object)(object)player != (Object)null && ((Character)player).IsTeleporting() && waited < 40f)
			{
				waited += Time.deltaTime;
				yield return null;
			}
			if ((Object)(object)player == (Object)null || (Object)(object)player != (Object)(object)Player.m_localPlayer || ((Character)player).IsTeleporting() || ((Character)player).IsDead())
			{
				yield break;
			}
			for (int attempt = 0; attempt < 3; attempt++)
			{
				if (!((Object)(object)player != (Object)null))
				{
					break;
				}
				if (PlaceAll(player, followers) == 0)
				{
					break;
				}
				yield return (object)new WaitForSeconds(2f);
			}
		}

		private static int PlaceAll(Player player, List<ZDOID> followers)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: 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)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			string playerName = player.GetPlayerName();
			int num = 0;
			for (int i = 0; i < followers.Count; i++)
			{
				ZDO zDO = ZDOMan.instance.GetZDO(followers[i]);
				if (zDO != null && FollowerRules.IsFollowing(zDO.GetString(ZDOVars.s_follow, ""), playerName) && !(Vector3.Distance(zDO.GetPosition(), ((Component)player).transform.position) <= 15f))
				{
					Vector3 val = ArrivalSpot(((Component)player).transform.position, i, followers.Count);
					zDO.SetOwner(ZDOMan.GetSessionID());
					zDO.SetPosition(val);
					GameObject val2 = ZNetScene.instance.FindInstance(followers[i]);
					if ((Object)(object)val2 != (Object)null)
					{
						val2.transform.position = val;
					}
					num++;
					if (ImprovedTamesConfig.DebugLogging.Value)
					{
						ImprovedTamesPlugin.Log.LogInfo((object)$"Moved tame {followers[i]} to {val} for {playerName}");
					}
				}
			}
			return num;
		}

		private static Vector3 ArrivalSpot(Vector3 center, int index, int count)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: 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_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			var (num, num2) = FollowerRules.ArrivalOffset(index, count, ImprovedTamesConfig.ArrivalRadius.Value);
			Vector3 val = default(Vector3);
			((Vector3)(ref val))..ctor(center.x + num, center.y, center.z + num2);
			float num3 = default(float);
			if (ZoneSystem.instance.FindFloor(val, ref num3) && Mathf.Abs(num3 - center.y) <= 3f)
			{
				val.y = num3 + 0.5f;
				return val;
			}
			return center + Vector3.up * 0.5f;
		}
	}
	[HarmonyPatch(typeof(TeleportWorld), "Teleport")]
	internal static class TeleportWorldPatch
	{
		private static void Prefix(Player player, out bool __state)
		{
			__state = (Object)(object)player != (Object)null && ((Character)player).IsTeleporting();
		}

		private static void Postfix(Player player, bool __state)
		{
			if (!__state && (Object)(object)player != (Object)null && (Object)(object)player == (Object)(object)Player.m_localPlayer && ((Character)player).IsTeleporting())
			{
				ImprovedTamesPlugin.Teleporter.OnPortalEntered(player);
			}
		}
	}
	internal static class ModInfo
	{
		public const string Guid = "com.robert.improvedtames";

		public const string Name = "ImprovedTames";

		public const string Version = "0.1.3";
	}
}
namespace ImprovedTames.Logic
{
	public static class FollowerRules
	{
		public static bool IsFollowing(string followName, string playerName)
		{
			if (!string.IsNullOrEmpty(followName))
			{
				return string.Equals(followName, playerName, StringComparison.Ordinal);
			}
			return false;
		}

		public static (float X, float Z) ArrivalOffset(int index, int count, float radius)
		{
			double num = Math.PI * 2.0 * (double)index / (double)Math.Max(count, 1);
			return (X: (float)(Math.Cos(num) * (double)radius), Z: (float)(Math.Sin(num) * (double)radius));
		}
	}
}