Decompiled source of PierSupports v1.0.0

PierSupports.dll

Decompiled 8 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text.RegularExpressions;
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_guiutils")]
[assembly: IgnoresAccessChecksTo("assembly_utils")]
[assembly: IgnoresAccessChecksTo("assembly_valheim")]
[assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")]
[assembly: AssemblyCompany("PierSupports")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("PierSupports")]
[assembly: AssemblyTitle("PierSupports")]
[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 PierSupports
{
	[HarmonyPatch]
	internal static class Piece_SetCreator_Patch
	{
		private static MethodBase TargetMethod()
		{
			PierBuilder.SetCreatorMethod = AccessTools.GetDeclaredMethods(typeof(Piece)).First((MethodInfo m) => m.Name == "SetCreator" && m.GetParameters().Length >= 1 && m.GetParameters()[0].ParameterType == typeof(long));
			return PierBuilder.SetCreatorMethod;
		}

		private static void Postfix(Piece __instance, object[] __args)
		{
			if (!PierBuilder.Spawning && !((Object)(object)__instance == (Object)null))
			{
				Player localPlayer = Player.m_localPlayer;
				if (!((Object)(object)localPlayer == (Object)null) && __instance.GetCreator() == localPlayer.GetPlayerID() && PierBuilder.KeyHeld())
				{
					PierBuilder.TryExtend(__instance, localPlayer, (object[])__args.Clone());
				}
			}
		}
	}
	[HarmonyPatch(typeof(WearNTear), "UpdateSupport")]
	internal static class WearNTear_UpdateSupport_Patch
	{
		private static void Postfix(WearNTear __instance)
		{
			if (Plugin.ForceGroundedSupport.Value)
			{
				ZNetView nview = __instance.m_nview;
				if (!((Object)(object)nview == (Object)null) && nview.IsValid() && nview.IsOwner() && nview.GetZDO().GetBool(PierBuilder.SegmentKey, false) && PierBuilder.IsChainGrounded(((Component)__instance).gameObject))
				{
					float num = default(float);
					float num2 = default(float);
					float num3 = default(float);
					float num4 = default(float);
					__instance.GetMaterialProperties(ref num, ref num2, ref num3, ref num4);
					__instance.m_support = num;
					nview.GetZDO().Set(ZDOVars.s_support, num);
				}
			}
		}
	}
	[HarmonyPatch(typeof(Terminal), "InitTerminal")]
	internal static class Terminal_InitTerminal_Patch
	{
		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static ConsoleEvent <>9__1_0;

			public static ConsoleEvent <>9__1_1;

			public static ConsoleEvent <>9__1_2;

			internal void <Postfix>b__1_0(ConsoleEventArgs args)
			{
				if ((Object)(object)ZNetScene.instance == (Object)null)
				{
					return;
				}
				List<string> list = new List<string>();
				foreach (GameObject prefab in ZNetScene.instance.m_prefabs)
				{
					if ((Object)(object)prefab == (Object)null)
					{
						continue;
					}
					Piece component = prefab.GetComponent<Piece>();
					if (!((Object)(object)component == (Object)null))
					{
						string name = ((Object)prefab).name;
						bool flag = Plugin.IsEligible(name);
						bool flag2 = name.IndexOf("pole", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("pillar", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("column", StringComparison.OrdinalIgnoreCase) >= 0;
						if (flag || flag2)
						{
							list.Add((flag ? "[x]" : "[ ]") + " " + name + "  (" + Localization.instance.Localize(component.m_name) + ")");
						}
					}
				}
				list.Sort(StringComparer.OrdinalIgnoreCase);
				foreach (string item in list)
				{
					args.Context.AddString(item);
					Plugin.Log.LogInfo((object)("pier_list: " + item));
				}
				args.Context.AddString($"{list.Count} piece(s). Also written to BepInEx/LogOutput.log.");
			}

			internal void <Postfix>b__1_1(ConsoleEventArgs args)
			{
				//IL_0016: Unknown result type (might be due to invalid IL or missing references)
				Player localPlayer = Player.m_localPlayer;
				if (!((Object)(object)localPlayer == (Object)null))
				{
					if (!PierBuilder.TryGetGroundY(((Component)localPlayer).transform.position, out var y))
					{
						args.Context.AddString("No terrain found below.");
						return;
					}
					float waterLevel = ZoneSystem.instance.m_waterLevel;
					args.Context.AddString($"Ground Y: {y:F1}  Water Y: {waterLevel:F1}  Water depth: {Mathf.Max(0f, waterLevel - y):F1} m");
				}
			}

			internal void <Postfix>b__1_2(ConsoleEventArgs args)
			{
				//IL_0015: Unknown result type (might be due to invalid IL or missing references)
				Plugin.ReloadConfig();
				args.Context.AddString($"PierSupports config reloaded. Extend key: {Plugin.ExtendKey.Value}");
			}
		}

		private static bool _registered;

		private static void Postfix()
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Expected O, but got Unknown
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Expected O, but got Unknown
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Expected O, but got Unknown
			if (_registered)
			{
				return;
			}
			_registered = true;
			object obj = <>c.<>9__1_0;
			if (obj == null)
			{
				ConsoleEvent val = delegate(ConsoleEventArgs args)
				{
					if (!((Object)(object)ZNetScene.instance == (Object)null))
					{
						List<string> list = new List<string>();
						foreach (GameObject prefab in ZNetScene.instance.m_prefabs)
						{
							if (!((Object)(object)prefab == (Object)null))
							{
								Piece component = prefab.GetComponent<Piece>();
								if (!((Object)(object)component == (Object)null))
								{
									string name = ((Object)prefab).name;
									bool flag = Plugin.IsEligible(name);
									bool flag2 = name.IndexOf("pole", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("pillar", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("column", StringComparison.OrdinalIgnoreCase) >= 0;
									if (flag || flag2)
									{
										list.Add((flag ? "[x]" : "[ ]") + " " + name + "  (" + Localization.instance.Localize(component.m_name) + ")");
									}
								}
							}
						}
						list.Sort(StringComparer.OrdinalIgnoreCase);
						foreach (string item in list)
						{
							args.Context.AddString(item);
							Plugin.Log.LogInfo((object)("pier_list: " + item));
						}
						args.Context.AddString($"{list.Count} piece(s). Also written to BepInEx/LogOutput.log.");
					}
				};
				<>c.<>9__1_0 = val;
				obj = (object)val;
			}
			new ConsoleCommand("pier_list", "[PierSupports] List pole/pillar/column pieces and whether they are eligible", (ConsoleEvent)obj, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
			object obj2 = <>c.<>9__1_1;
			if (obj2 == null)
			{
				ConsoleEvent val2 = delegate(ConsoleEventArgs args)
				{
					//IL_0016: Unknown result type (might be due to invalid IL or missing references)
					Player localPlayer = Player.m_localPlayer;
					if (!((Object)(object)localPlayer == (Object)null))
					{
						if (!PierBuilder.TryGetGroundY(((Component)localPlayer).transform.position, out var y))
						{
							args.Context.AddString("No terrain found below.");
						}
						else
						{
							float waterLevel = ZoneSystem.instance.m_waterLevel;
							args.Context.AddString($"Ground Y: {y:F1}  Water Y: {waterLevel:F1}  Water depth: {Mathf.Max(0f, waterLevel - y):F1} m");
						}
					}
				};
				<>c.<>9__1_1 = val2;
				obj2 = (object)val2;
			}
			new ConsoleCommand("pier_depth", "[PierSupports] Show ground height and water depth under you", (ConsoleEvent)obj2, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
			object obj3 = <>c.<>9__1_2;
			if (obj3 == null)
			{
				ConsoleEvent val3 = delegate(ConsoleEventArgs args)
				{
					//IL_0015: Unknown result type (might be due to invalid IL or missing references)
					Plugin.ReloadConfig();
					args.Context.AddString($"PierSupports config reloaded. Extend key: {Plugin.ExtendKey.Value}");
				};
				<>c.<>9__1_2 = val3;
				obj3 = (object)val3;
			}
			new ConsoleCommand("pier_reload", "[PierSupports] Reload the config file", (ConsoleEvent)obj3, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
		}
	}
	internal static class PierBuilder
	{
		internal static readonly int SegmentKey = StringExtensionMethods.GetStableHashCode("squatch_pier_segment");

		internal static bool Spawning;

		internal static MethodInfo SetCreatorMethod;

		private const float UprightToleranceDeg = 10f;

		private const float GroundTolerance = 0.25f;

		private static int _terrainMask;

		private static int _pieceMask;

		private static readonly Collider[] Overlap = (Collider[])(object)new Collider[32];

		internal static int TerrainMask
		{
			get
			{
				if (_terrainMask == 0)
				{
					return _terrainMask = LayerMask.GetMask(new string[1] { "terrain" });
				}
				return _terrainMask;
			}
		}

		internal static int PieceMask
		{
			get
			{
				if (_pieceMask == 0)
				{
					return _pieceMask = LayerMask.GetMask(new string[2] { "piece", "piece_nonsolid" });
				}
				return _pieceMask;
			}
		}

		internal static bool KeyHeld()
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			return UnityInput.Current.GetKey(Plugin.ExtendKey.Value);
		}

		internal static void TryExtend(Piece top, Player player, object[] creatorArgs)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: 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_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
			string prefabName = Utils.GetPrefabName(((Component)top).gameObject);
			if (!Plugin.IsEligible(prefabName))
			{
				Plugin.Debug(prefabName + " is not in the eligible list; skipping.");
				return;
			}
			if (Vector3.Angle(((Component)top).transform.up, Vector3.up) > 10f)
			{
				Plugin.Debug(prefabName + " is not upright; skipping.");
				return;
			}
			GameObject prefab = ZNetScene.instance.GetPrefab(prefabName);
			if ((Object)(object)prefab == (Object)null)
			{
				return;
			}
			Physics.SyncTransforms();
			if (!TryGetBounds(((Component)top).gameObject, out var bounds) || ((Bounds)(ref bounds)).size.y < 0.25f)
			{
				return;
			}
			float y = ((Bounds)(ref bounds)).size.y;
			if (!TryGetGroundY(((Bounds)(ref bounds)).center, out var y2))
			{
				((Character)player).Message((MessageType)2, "Pier: no ground found below", 0, (Sprite)null, false);
				return;
			}
			float num = ((Bounds)(ref bounds)).min.y - y2;
			if (num <= 0.05f)
			{
				return;
			}
			if (Plugin.RequireWater.Value && y2 >= ZoneSystem.instance.m_waterLevel)
			{
				Plugin.Debug("Ground below is not underwater and RequireWater is on; skipping.");
				return;
			}
			if (num > Plugin.MaxDepth.Value)
			{
				((Character)player).Message((MessageType)2, $"Pier: {num:F1}m to ground exceeds MaxDepth ({Plugin.MaxDepth.Value:F0}m)", 0, (Sprite)null, false);
				return;
			}
			int num2 = Mathf.CeilToInt(num / y);
			bool flag = player.NoCostCheat() || ZoneSystem.instance.GetGlobalKey((GlobalKeys)24);
			if (!flag && !CanAfford(player, top, num2, out var missing))
			{
				((Character)player).Message((MessageType)2, $"Pier needs {num2} more segment(s). Missing: {missing}", 0, (Sprite)null, false);
				return;
			}
			Spawning = true;
			try
			{
				MarkSegment(((Component)top).gameObject);
				MethodInfo methodInfo = AccessTools.Method(typeof(WearNTear), "OnPlaced", (Type[])null, (Type[])null);
				for (int i = 1; i <= num2; i++)
				{
					Vector3 val = ((Component)top).transform.position - Vector3.up * y * (float)i;
					GameObject obj = Object.Instantiate<GameObject>(prefab, val, ((Component)top).transform.rotation);
					Piece component = obj.GetComponent<Piece>();
					if ((Object)(object)component != (Object)null && SetCreatorMethod != null)
					{
						SetCreatorMethod.Invoke(component, creatorArgs);
					}
					MarkSegment(obj);
					WearNTear component2 = obj.GetComponent<WearNTear>();
					if ((Object)(object)component2 != (Object)null && methodInfo != null)
					{
						methodInfo.Invoke(component2, null);
					}
				}
				if (!flag)
				{
					Consume(player, top, num2);
				}
				((Character)player).Message((MessageType)1, $"Pier extended {num2} segment(s), {num:F1}m to ground", 0, (Sprite)null, false);
				Plugin.Debug($"Extended {prefabName}: {num2} x {y:F2}m, gap {num:F2}m");
			}
			finally
			{
				Spawning = false;
			}
		}

		private static bool CanAfford(Player player, Piece piece, int count, out string missing)
		{
			missing = null;
			Inventory inventory = ((Humanoid)player).GetInventory();
			Requirement[] resources = piece.m_resources;
			foreach (Requirement val in resources)
			{
				if (!((Object)(object)val?.m_resItem == (Object)null) && val.m_amount > 0)
				{
					string name = val.m_resItem.m_itemData.m_shared.m_name;
					int num = val.m_amount * count;
					int num2 = inventory.CountItems(name, -1, true);
					if (num2 < num)
					{
						missing = $"{Localization.instance.Localize(name)} {num2}/{num}";
						return false;
					}
				}
			}
			return true;
		}

		private static void Consume(Player player, Piece piece, int count)
		{
			Inventory inventory = ((Humanoid)player).GetInventory();
			Requirement[] resources = piece.m_resources;
			foreach (Requirement val in resources)
			{
				if (!((Object)(object)val?.m_resItem == (Object)null) && val.m_amount > 0)
				{
					inventory.RemoveItem(val.m_resItem.m_itemData.m_shared.m_name, val.m_amount * count, -1, true);
				}
			}
		}

		private static void MarkSegment(GameObject go)
		{
			ZNetView component = go.GetComponent<ZNetView>();
			ZDO obj = ((component != null) ? component.GetZDO() : null);
			if (obj != null)
			{
				obj.Set(SegmentKey, true);
			}
		}

		internal static bool IsSegment(GameObject go)
		{
			ZNetView component = go.GetComponent<ZNetView>();
			if ((Object)(object)component != (Object)null && component.IsValid())
			{
				return component.GetZDO().GetBool(SegmentKey, false);
			}
			return false;
		}

		internal static bool IsChainGrounded(GameObject start)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			HashSet<GameObject> hashSet = new HashSet<GameObject>();
			GameObject val = start;
			for (int i = 0; i < 128; i++)
			{
				if (!((Object)(object)val != (Object)null))
				{
					break;
				}
				if (!hashSet.Add(val))
				{
					break;
				}
				if (!TryGetBounds(val, out var bounds))
				{
					return false;
				}
				if (TryGetGroundY(((Bounds)(ref bounds)).center, out var y) && y >= ((Bounds)(ref bounds)).min.y - 0.25f)
				{
					return true;
				}
				val = FindSegmentBelow(val, bounds);
			}
			return false;
		}

		private static GameObject FindSegmentBelow(GameObject current, Bounds b)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			int num = Physics.OverlapBoxNonAlloc(new Vector3(((Bounds)(ref b)).center.x, ((Bounds)(ref b)).min.y, ((Bounds)(ref b)).center.z), new Vector3(0.1f, 0.2f, 0.1f), Overlap, Quaternion.identity, PieceMask);
			for (int i = 0; i < num; i++)
			{
				WearNTear componentInParent = ((Component)Overlap[i]).GetComponentInParent<WearNTear>();
				if (!((Object)(object)componentInParent == (Object)null))
				{
					GameObject gameObject = ((Component)componentInParent).gameObject;
					if (!((Object)(object)gameObject == (Object)(object)current) && IsSegment(gameObject) && TryGetBounds(gameObject, out var bounds) && ((Bounds)(ref bounds)).center.y < ((Bounds)(ref b)).center.y)
					{
						return gameObject;
					}
				}
			}
			return null;
		}

		internal static bool TryGetBounds(GameObject go, out Bounds bounds)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			bounds = default(Bounds);
			bool flag = false;
			Collider[] componentsInChildren = go.GetComponentsInChildren<Collider>();
			foreach (Collider val in componentsInChildren)
			{
				if (val.enabled && !val.isTrigger)
				{
					if (!flag)
					{
						bounds = val.bounds;
						flag = true;
					}
					else
					{
						((Bounds)(ref bounds)).Encapsulate(val.bounds);
					}
				}
			}
			return flag;
		}

		internal static bool TryGetGroundY(Vector3 at, out float y)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			RaycastHit val = default(RaycastHit);
			if (Physics.Raycast(new Vector3(at.x, at.y + 500f, at.z), Vector3.down, ref val, 2000f, TerrainMask))
			{
				y = ((RaycastHit)(ref val)).point.y;
				return true;
			}
			y = 0f;
			return false;
		}
	}
	[BepInPlugin("squatch.piersupports", "PierSupports", "1.0.0")]
	public class Plugin : BaseUnityPlugin
	{
		public const string Guid = "squatch.piersupports";

		public const string Name = "PierSupports";

		public const string Version = "1.0.0";

		internal static Plugin Instance;

		internal static ManualLogSource Log;

		internal static ConfigEntry<KeyCode> ExtendKey;

		internal static ConfigEntry<float> MaxDepth;

		internal static ConfigEntry<bool> RequireWater;

		internal static ConfigEntry<bool> ForceGroundedSupport;

		internal static ConfigEntry<string> IncludePatterns;

		internal static ConfigEntry<string> ExcludePatterns;

		internal static ConfigEntry<bool> VerboseLogging;

		private static List<Regex> _include = new List<Regex>();

		private static List<Regex> _exclude = new List<Regex>();

		private Harmony _harmony;

		private void Awake()
		{
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Expected O, but got Unknown
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Expected O, but got Unknown
			//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			ExtendKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Controls", "ExtendKey", (KeyCode)308, "Hold this key while placing a vertical support to extend it down to the ground below. Uses Unity KeyCode names: LeftAlt, RightAlt, LeftControl, RightControl, LeftShift, RightShift, Mouse3, Mouse4, or any other key (e.g. Z, CapsLock).");
			MaxDepth = ((BaseUnityPlugin)this).Config.Bind<float>("Placement", "MaxDepth", 32f, new ConfigDescription("Maximum distance (meters) a pier will extend below the placed piece. Guards against misclicks over deep water.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 128f), Array.Empty<object>()));
			RequireWater = ((BaseUnityPlugin)this).Config.Bind<bool>("Placement", "RequireWater", false, "Only extend when the ground below is underwater. False (default) also extends down to dry ground (cliffs, ravines).");
			ForceGroundedSupport = ((BaseUnityPlugin)this).Config.Bind<bool>("Structure", "ForceGroundedSupport", true, "Pier segments whose stack reaches the ground get full (grounded) structural support no matter how tall the stack is. Every player who builds or plays near the piers should run the mod with the same setting.");
			IncludePatterns = ((BaseUnityPlugin)this).Config.Bind<string>("Pieces", "IncludePatterns", "*pole*,*pillar*,*column*", "Comma-separated prefab names or * wildcards for pieces that can be extended. Run pier_list in the F5 console to see which pieces match.");
			ExcludePatterns = ((BaseUnityPlugin)this).Config.Bind<string>("Pieces", "ExcludePatterns", "piece_dvergr_*,piece_maypole,*_worn,Piece_grausten_pillarbeam_*,Piece_grausten_pillar_arch*,Piece_grausten_pillarbase_tapered*", "Comma-separated prefab names or * wildcards to exclude, even if they match IncludePatterns.");
			VerboseLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "VerboseLogging", false, "Log placement decisions to BepInEx/LogOutput.log.");
			RebuildPatterns();
			IncludePatterns.SettingChanged += delegate
			{
				RebuildPatterns();
			};
			ExcludePatterns.SettingChanged += delegate
			{
				RebuildPatterns();
			};
			_harmony = new Harmony("squatch.piersupports");
			_harmony.PatchAll();
			Log.LogInfo((object)string.Format("{0} {1} loaded. Extend key: {2}", "PierSupports", "1.0.0", ExtendKey.Value));
		}

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

		internal static void ReloadConfig()
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			((BaseUnityPlugin)Instance).Config.Reload();
			RebuildPatterns();
			Log.LogInfo((object)$"Config reloaded. Extend key: {ExtendKey.Value}");
		}

		internal static bool IsEligible(string prefabName)
		{
			if (string.IsNullOrEmpty(prefabName))
			{
				return false;
			}
			if (_include.Any((Regex r) => r.IsMatch(prefabName)))
			{
				return !_exclude.Any((Regex r) => r.IsMatch(prefabName));
			}
			return false;
		}

		internal static void Debug(string msg)
		{
			if (VerboseLogging.Value)
			{
				Log.LogInfo((object)msg);
			}
		}

		private static void RebuildPatterns()
		{
			_include = Parse(IncludePatterns.Value);
			_exclude = Parse(ExcludePatterns.Value);
		}

		private static List<Regex> Parse(string value)
		{
			return (from p in (value ?? string.Empty).Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries)
				select p.Trim() into p
				where p.Length > 0
				select new Regex("^" + Regex.Escape(p).Replace("\\*", ".*") + "$", RegexOptions.IgnoreCase)).ToList();
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}