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(); if ((Object)(object)component == (Object)null) { return true; } Humanoid component2 = ((Component)__instance).gameObject.GetComponent(); if ((Object)(object)component2 == (Object)null) { return true; } Inventory inventory = component2.GetInventory(); if (inventory == null) { return true; } List 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, "" + text + " cannot teleport home while carrying non-teleportable items (" + text2 + ")!", 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(); if (!((Object)(object)setupComponent != (Object)null)) { yield break; } try { ZNetView nview = ((Component)aiInstance).GetComponent(); 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(); 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(); } } }