using System; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Logging; using HarmonyLib; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("IronLabs.PvPEnabled")] [assembly: AssemblyDescription("Keeps Valheim PvP permanently enabled.")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("IronLabs.PvPEnabled")] [assembly: AssemblyCopyright("Copyright © 2026")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("86006976-5150-4F0A-9A91-2104A9AC5C00")] [assembly: AssemblyFileVersion("1.0.1")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyVersion("1.0.1.0")] namespace IronLabs.PvPEnabled; internal static class ModLog { private static ManualLogSource _logger; private static string _pluginName; internal static void Initialize(ManualLogSource logger, string pluginName) { _logger = logger; _pluginName = pluginName; } internal static void Clear() { _logger = null; _pluginName = null; } internal static void LogDebug(object message) { Write((LogLevel)32, message); } internal static void LogInfo(object message) { Write((LogLevel)16, message); } private static void Write(LogLevel level, object message) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) ManualLogSource logger = _logger; if (logger != null) { logger.Log(level, message); } } } [BepInPlugin("IronLabs.PvPEnabled", "IronLabs.PvPEnabled", "1.0.1")] public sealed class PvPEnabledPlugin : BaseUnityPlugin { private const string PluginGuid = "IronLabs.PvPEnabled"; private const string PluginName = "IronLabs.PvPEnabled"; private const string PluginVersion = "1.0.1"; private const float ActivationDelaySeconds = 5f; private readonly Harmony _harmony = new Harmony("IronLabs.PvPEnabled"); private static bool _patchesApplied; private Player _trackedPlayer; private float _activationTime; private static bool _waitingForRespawn; internal static bool EnforcementEnabled { get; private set; } private void Awake() { ModLog.Initialize(((BaseUnityPlugin)this).Logger, "IronLabs.PvPEnabled"); PatchOwnNamespace(); ModLog.LogInfo("IronLabs.PvPEnabled 1.0.1 is loaded."); } private void PatchOwnNamespace() { if (_patchesApplied) { ModLog.LogDebug("Harmony patches are already active; skipping registration."); return; } string text = typeof(PvPEnabledPlugin).Namespace; Type[] types = Assembly.GetExecutingAssembly().GetTypes(); foreach (Type type in types) { if (type.Namespace == text) { _harmony.CreateClassProcessor(type).Patch(); } } _patchesApplied = true; ModLog.LogDebug("Harmony patches were applied for the plugin namespace."); } private void Update() { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { ResetPlayerTracking(); } else if (_waitingForRespawn) { HandleRespawn(localPlayer); } else if ((Object)(object)_trackedPlayer != (Object)(object)localPlayer) { BeginActivationDelay(localPlayer); } else if (!EnforcementEnabled && Time.unscaledTime >= _activationTime) { EnforcementEnabled = true; localPlayer.SetPVP(true); ModLog.LogDebug("PvP was enabled after the five-second delay."); } } internal static void HandleLocalPlayerDeath(Player player) { EnforcementEnabled = false; _waitingForRespawn = true; player.SetPVP(false); ModLog.LogDebug("PvP was disabled when the local player died."); } private void HandleRespawn(Player player) { if (!((Character)player).IsDead()) { _waitingForRespawn = false; BeginActivationDelay(player); ModLog.LogDebug("The post-respawn PvP activation delay started."); } } private void BeginActivationDelay(Player player) { _trackedPlayer = player; EnforcementEnabled = false; player.SetPVP(false); _activationTime = Time.unscaledTime + 5f; ModLog.LogDebug("Started the five-second PvP activation delay."); } private void ResetPlayerTracking() { _trackedPlayer = null; EnforcementEnabled = false; } private void OnDestroy() { ResetPlayerTracking(); _waitingForRespawn = false; if (_patchesApplied) { _harmony.UnpatchSelf(); _patchesApplied = false; } ModLog.Clear(); } } [HarmonyPatch(typeof(Player), "SetPVP")] internal static class PreventPvpDisablePatch { private static void Prefix(Player __instance, ref bool enabled) { if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer) { enabled = PvPEnabledPlugin.EnforcementEnabled; } } } [HarmonyPatch(typeof(Player), "OnDeath")] internal static class DisablePvpOnDeathPatch { private static void Postfix(Player __instance) { if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer) { PvPEnabledPlugin.HandleLocalPlayerDeath(__instance); } } } [HarmonyPatch(typeof(InventoryGui), "Awake")] internal static class HidePvpTogglePatch { private static void Postfix(InventoryGui __instance) { if ((Object)(object)__instance.m_pvp != (Object)null) { ((Component)__instance.m_pvp).gameObject.SetActive(false); ModLog.LogDebug("The vanilla PvP toggle was hidden."); } } }