Decompiled source of Companion No Go Home Fix v1.0.0

Björnulfr-CompanionNoGoHome.dll

Decompiled 5 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 System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Logging;
using Companions;
using HarmonyLib;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("Björnulfr-CompanionNoGoHome")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("Björnulfr-CompanionNoGoHome")]
[assembly: AssemblyTitle("Björnulfr-CompanionNoGoHome")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace ValheimCompanionExploitFix;

[BepInPlugin("com.bjornulfr.companionnogohome", "Companion No Go Home Fix", "1.0.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class CompanionExploitFixPlugin : BaseUnityPlugin
{
	[HarmonyPatch(typeof(CompanionAI))]
	public static class CompanionAI_Exploit_Patch
	{
		[HarmonyPatch("TeleportToHome")]
		[HarmonyPrefix]
		public static bool TeleportToHome_Prefix(CompanionAI __instance)
		{
			Character component = ((Component)__instance).gameObject.GetComponent<Character>();
			if ((Object)(object)component == (Object)null)
			{
				return true;
			}
			Humanoid component2 = ((Component)__instance).gameObject.GetComponent<Humanoid>();
			if ((Object)(object)component2 == (Object)null)
			{
				return true;
			}
			Inventory inventory = component2.GetInventory();
			if (inventory == null)
			{
				return true;
			}
			List<ItemData> allItems = inventory.GetAllItems();
			foreach (ItemData item in allItems)
			{
				if (item?.m_shared == null || item.m_shared.m_teleportable)
				{
					continue;
				}
				string text = component.m_name ?? "Your companion";
				string text2 = item.m_shared.m_name;
				try
				{
					Type type = typeof(Player).Assembly.GetType("Localization");
					if (type != null)
					{
						object obj = type.GetProperty("instance", BindingFlags.Static | BindingFlags.Public)?.GetValue(null);
						MethodInfo method = type.GetMethod("Localize", new Type[1] { typeof(string) });
						if (obj != null && method != null)
						{
							text2 = (string)method.Invoke(obj, new object[1] { item.m_shared.m_name });
						}
					}
				}
				catch (Exception)
				{
				}
				Player localPlayer = Player.m_localPlayer;
				if ((Object)(object)localPlayer != (Object)null)
				{
					((Character)localPlayer).Message((MessageType)2, "<color=red>" + text + " cannot teleport home while carrying non-teleportable items (" + text2 + ")!</color>", 0, (Sprite)null);
				}
				Log.LogWarning((object)("Blocked exploit attempt! " + text + " was prevented from teleporting with " + text2 + "."));
				((BaseAI)__instance).StopMoving();
				((MonoBehaviour)__instance).StartCoroutine(ResetCompanionStateRoutine(__instance, component));
				return false;
			}
			return true;
		}

		private static IEnumerator ResetCompanionStateRoutine(CompanionAI aiInstance, Character companionChar)
		{
			yield return (object)new WaitForSecondsRealtime(2f);
			if ((Object)(object)aiInstance == (Object)null || (Object)(object)companionChar == (Object)null || companionChar.GetHealth() <= 0f)
			{
				yield break;
			}
			CompanionSetup setupComponent = ((Component)aiInstance).GetComponent<CompanionSetup>();
			if (!((Object)(object)setupComponent != (Object)null))
			{
				yield break;
			}
			try
			{
				ZNetView nview = ((Component)aiInstance).GetComponent<ZNetView>();
				if ((Object)(object)nview != (Object)null && nview.GetZDO() != null && !nview.IsOwner())
				{
					nview.ClaimOwnership();
				}
				setStayHomeMethod?.Invoke(setupComponent, new object[1] { false });
				setFollowMethod?.Invoke(setupComponent, new object[1] { true });
				if ((Object)(object)Player.m_localPlayer != (Object)null)
				{
					aiInstance.SetFollowTarget(((Component)Player.m_localPlayer).gameObject);
				}
				cancelMoveTargetMethod?.Invoke(aiInstance, null);
				aiInstance.ClearTargets();
				((BaseAI)aiInstance).StopMoving();
				applyFollowModeMethod?.Invoke(setupComponent, new object[2] { 0, true });
				CompanionTalk talkComponent = ((Component)aiInstance).GetComponent<CompanionTalk>();
				if (!((Object)(object)talkComponent != (Object)null))
				{
					yield break;
				}
				Type localizationType = typeof(Player).Assembly.GetType("Localization");
				if (!(localizationType != null))
				{
					yield break;
				}
				object instance = localizationType.GetProperty("instance", BindingFlags.Static | BindingFlags.Public)?.GetValue(null);
				MethodInfo localizeMethod = localizationType.GetMethod("Localize", new Type[1] { typeof(string) });
				if (instance != null && localizeMethod != null)
				{
					string textChatter = (string)localizeMethod.Invoke(instance, new object[1] { "$hc_cmd_cancel_2" });
					if (!string.IsNullOrEmpty(textChatter))
					{
						talkComponent.Say(textChatter, false);
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogError((object)("Failed asynchronous background state recovery cleanup: " + ex.Message));
				}
			}
		}
	}

	public const string PluginGUID = "com.bjornulfr.companionnogohome";

	public const string PluginName = "Companion No Go Home Fix";

	public const string PluginVersion = "1.0.0";

	private static Harmony _harmony;

	internal static ManualLogSource Log;

	private static MethodInfo setStayHomeMethod;

	private static MethodInfo setFollowMethod;

	private static MethodInfo applyFollowModeMethod;

	private static MethodInfo cancelMoveTargetMethod;

	private void Awake()
	{
		//IL_008d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0097: Expected O, but got Unknown
		Log = ((BaseUnityPlugin)this).Logger;
		Log.LogInfo((object)"Companion No Go Home Fix v1.0.0 loading safely after main mod...");
		setStayHomeMethod = typeof(CompanionSetup).GetMethod("SetStayHome", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		setFollowMethod = typeof(CompanionSetup).GetMethod("SetFollow", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		applyFollowModeMethod = typeof(CompanionSetup).GetMethod("ApplyFollowMode", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		cancelMoveTargetMethod = typeof(CompanionAI).GetMethod("CancelMoveTarget", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		_harmony = new Harmony("com.bjornulfr.companionnogohome");
		_harmony.PatchAll();
	}

	private static void OnDestroy()
	{
		Harmony harmony = _harmony;
		if (harmony != null)
		{
			harmony.UnpatchSelf();
		}
	}
}