Decompiled source of StructureDamageManager v1.0.0

StructureDamageManager.dll

Decompiled 2 weeks ago
using System;
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.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("assembly_utils")]
[assembly: IgnoresAccessChecksTo("assembly_valheim")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("StructureDamageManager")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+a59541c05bc4a4c108b884cdfa3e1722c866c52c")]
[assembly: AssemblyProduct("StructureDamageManager")]
[assembly: AssemblyTitle("StructureDamageManager")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[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 StructureDamageManager
{
	internal static class AutoRepair
	{
		private static readonly Dictionary<WearNTear, float> damagedSince = new Dictionary<WearNTear, float>();

		internal static void Visit(WearNTear wnt, float time)
		{
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			if (!Plugin.AutoRepairEnabled.Value)
			{
				return;
			}
			if (wnt.m_healthPercentage >= 1f)
			{
				if (damagedSince.Count > 0)
				{
					damagedSince.Remove(wnt);
				}
			}
			else
			{
				if (!ProtectedPieces.IsProtected(wnt) || !wnt.m_nview.IsValid())
				{
					return;
				}
				if (wnt.m_nview.GetZDO().GetFloat(ZDOVars.s_health, wnt.m_health) >= wnt.m_health)
				{
					damagedSince.Remove(wnt);
					return;
				}
				if (!damagedSince.TryGetValue(wnt, out var value))
				{
					value = time;
					damagedSince[wnt] = value;
				}
				if (!(time - value < Plugin.AutoRepairDelay.Value) && PrivateArea.CheckAccess(((Component)wnt).transform.position, 0f, false, false))
				{
					damagedSince.Remove(wnt);
					if (wnt.Repair())
					{
						Plugin.Log.LogDebug((object)$"Repaired {((Object)((Component)wnt).gameObject).name} at {((Component)wnt).transform.position} after {time - value:F0} s (owner: {wnt.m_nview.IsOwner()})");
					}
				}
			}
		}

		internal static void Forget(WearNTear wnt)
		{
			if (damagedSince.Count > 0)
			{
				damagedSince.Remove(wnt);
			}
		}

		internal static void Reset()
		{
			damagedSince.Clear();
		}
	}
	public enum DamageMode
	{
		Off,
		NonEnvironment,
		Friendly,
		All
	}
	[BepInPlugin("rhenn.structuredamagemanager", "StructureDamageManager", "1.0.0")]
	public class Plugin : BaseUnityPlugin
	{
		public const string PluginGUID = "rhenn.structuredamagemanager";

		public const string PluginName = "StructureDamageManager";

		public const string PluginVersion = "1.0.0";

		internal static ManualLogSource Log;

		internal static ConfigEntry<bool> PreventRainDamage;

		internal static ConfigEntry<DamageMode> Mode;

		internal static ConfigEntry<bool> AutoRepairEnabled;

		internal static ConfigEntry<float> AutoRepairDelay;

		private readonly Harmony harmony = new Harmony("rhenn.structuredamagemanager");

		private void Awake()
		{
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			PreventRainDamage = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "PreventRainDamage", true, "Player-built pieces take no damage from rain or from standing in water. They still look wet. The only setting that is on by default.");
			Mode = ((BaseUnityPlugin)this).Config.Bind<DamageMode>("General", "DamageMode", DamageMode.Off, "Which damage player-built pieces are immune to.\nOff: vanilla, only PreventRainDamage applies.\nNonEnvironment: no damage from enemy creatures, tamed creatures or players (yourself included).\nFriendly: no damage from tamed creatures or players (yourself included); enemies still hit.\nAll: no damage of any kind: hits, rain, water, loss of support, ash, lava, snow, falling trees, fire, events.");
			AutoRepairEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("AutoRepair", "Enabled", false, "Damaged player-built pieces near you repair themselves to full health, silently, without a hammer or workbench. Pieces inside a ward you have no access to are left alone.");
			AutoRepairDelay = ((BaseUnityPlugin)this).Config.Bind<float>("AutoRepair", "DelaySeconds", 60f, new ConfigDescription("How long a piece must stay damaged before it is repaired. 0 repairs at once; a delay lets a raid leave its marks until it is over.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 600f), Array.Empty<object>()));
			AutoRepairEnabled.SettingChanged += delegate
			{
				AutoRepair.Reset();
			};
			harmony.PatchAll(Assembly.GetExecutingAssembly());
			Log.LogInfo((object)(string.Format("{0} {1} loaded. PreventRainDamage = {2}, ", "StructureDamageManager", "1.0.0", PreventRainDamage.Value) + $"DamageMode = {Mode.Value}, AutoRepair = {AutoRepairEnabled.Value} ({AutoRepairDelay.Value} s)"));
		}

		private void OnDestroy()
		{
			harmony.UnpatchSelf();
		}
	}
	internal static class ProtectedPieces
	{
		private static readonly HashSet<WearNTear> vehicles = new HashSet<WearNTear>();

		internal static void Register(WearNTear wnt)
		{
			if ((Object)(object)((Component)wnt).GetComponent<Ship>() != (Object)null || (Object)(object)((Component)wnt).GetComponent<Vagon>() != (Object)null)
			{
				vehicles.Add(wnt);
			}
		}

		internal static void Forget(WearNTear wnt)
		{
			vehicles.Remove(wnt);
		}

		internal static bool IsProtected(WearNTear wnt)
		{
			if ((Object)(object)wnt.m_piece != (Object)null && wnt.m_piece.IsPlacedByPlayer())
			{
				return !vehicles.Contains(wnt);
			}
			return false;
		}
	}
}
namespace StructureDamageManager.Patches
{
	[HarmonyPatch(typeof(WearNTear), "Awake")]
	internal static class WearNTear_Awake_Patch
	{
		private static void Postfix(WearNTear __instance)
		{
			ProtectedPieces.Register(__instance);
		}
	}
	[HarmonyPatch(typeof(WearNTear), "OnDestroy")]
	internal static class WearNTear_OnDestroy_Patch
	{
		private static void Postfix(WearNTear __instance)
		{
			ProtectedPieces.Forget(__instance);
			AutoRepair.Forget(__instance);
		}
	}
	[HarmonyPatch(typeof(WearNTear), "UpdateWear")]
	internal static class WearNTear_UpdateWear_Patch
	{
		private static void Prefix(WearNTear __instance, float time)
		{
			if ((Plugin.PreventRainDamage.Value || Plugin.Mode.Value == DamageMode.All) && ProtectedPieces.IsProtected(__instance))
			{
				__instance.m_rainTimer = time;
			}
		}

		private static void Postfix(WearNTear __instance, float time)
		{
			AutoRepair.Visit(__instance, time);
		}
	}
	[HarmonyPatch(typeof(WearNTear), "RPC_Damage")]
	internal static class WearNTear_RPC_Damage_Patch
	{
		private static bool Prefix(WearNTear __instance, long sender, HitData hit)
		{
			DamageMode value = Plugin.Mode.Value;
			if (value == DamageMode.Off || !ProtectedPieces.IsProtected(__instance))
			{
				return true;
			}
			if (value == DamageMode.All)
			{
				return false;
			}
			Character attacker = hit.GetAttacker();
			if ((Object)(object)attacker == (Object)null)
			{
				return true;
			}
			bool flag = attacker.IsPlayer() || attacker.IsTamed();
			bool flag2 = flag || value == DamageMode.NonEnvironment;
			if (flag2)
			{
				Plugin.Log.LogDebug((object)string.Format("Blocked {0:F0} damage to {1} from {2} ({3}, {4})", hit.GetTotalDamage(), ((Object)((Component)__instance).gameObject).name, attacker.m_name, flag ? "friendly" : "enemy", value));
			}
			return !flag2;
		}
	}
	[HarmonyPatch(typeof(WearNTear), "ApplyDamage")]
	internal static class WearNTear_ApplyDamage_Patch
	{
		private static bool Prefix(WearNTear __instance, ref bool __result)
		{
			if (Plugin.Mode.Value != DamageMode.All || !ProtectedPieces.IsProtected(__instance))
			{
				return true;
			}
			__result = false;
			return false;
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}