Decompiled source of WoodRamps v1.0.0

WoodRamps.dll

Decompiled 21 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
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 Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: IgnoresAccessChecksTo("assembly_guiutils")]
[assembly: IgnoresAccessChecksTo("assembly_valheim")]
[assembly: AssemblyCompany("WoodRamps")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("WoodRamps")]
[assembly: AssemblyTitle("WoodRamps")]
[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 WoodFloors2645
{
	internal static class ConfigManager
	{
		internal static ConfigEntry<float> DynamicFriction;

		internal static ConfigEntry<float> StaticFriction;

		internal static ConfigEntry<int> WoodCost;

		internal static ConfigEntry<bool> RequireWorkbench;

		internal static void Init(ConfigFile config)
		{
			DynamicFriction = config.Bind<float>("Physics", "DynamicFriction", 0.05f, "Dynamic friction on the angled wood ramps (lower = better for Shield Sledding).");
			StaticFriction = config.Bind<float>("Physics", "StaticFriction", 0.05f, "Static friction on the angled wood ramps.");
			WoodCost = config.Bind<int>("Building", "WoodCost", 2, "Wood required to place each wood ramp piece (vanilla wood floor is 2).");
			RequireWorkbench = config.Bind<bool>("Building", "RequireWorkbench", true, "If true, pieces require a nearby Workbench like vanilla wood floors.");
		}
	}
	internal static class FloorPrefabBuilder
	{
		internal const string VisualChildName = "FloorVisual";

		internal const string ColliderChildName = "FloorCollider";

		internal const float HalfSize = 1f;

		internal static GameObject CreateAngledFloor(string pieceName, float angleDegrees, bool rotateTexture90, string tokenName, string tokenDescription)
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = PrefabManager.Instance.CreateClonedPrefab(pieceName, "wood_floor");
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Log.LogError((object)"Could not clone vanilla prefab 'wood_floor'.");
				return null;
			}
			((Object)val).name = pieceName;
			AngleVanillaFloor(val, angleDegrees, rotateTexture90);
			FinalizePiece(val, tokenName, tokenDescription);
			val.transform.localScale = Vector3.one;
			return val;
		}

		private static void AngleVanillaFloor(GameObject prefab, float angleDegrees, bool rotateTexture90)
		{
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Expected O, but got Unknown
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01af: Unknown result type (might be due to invalid IL or missing references)
			StripColliders(prefab);
			ClearSnapPointChildren(prefab);
			StripChildWearNTear(prefab);
			List<Transform> list = new List<Transform>();
			for (int i = 0; i < prefab.transform.childCount; i++)
			{
				Transform child = prefab.transform.GetChild(i);
				if ((Object)(object)child != (Object)null)
				{
					list.Add(child);
				}
			}
			GameObject val = new GameObject("FloorVisual");
			val.transform.SetParent(prefab.transform, false);
			val.transform.localPosition = Vector3.zero;
			val.transform.localRotation = Quaternion.identity;
			val.transform.localScale = Vector3.one;
			foreach (Transform item in list)
			{
				if (!((Object)(object)item == (Object)null) && !((Object)(object)item == (Object)(object)val.transform))
				{
					item.SetParent(val.transform, false);
				}
			}
			Quaternion val2 = Quaternion.Euler(angleDegrees, 0f, 0f);
			if (rotateTexture90)
			{
				Quaternion val3 = Quaternion.Euler(0f, 90f, 0f);
				val.transform.localRotation = val2 * val3;
				Plugin.Log.LogInfo((object)$"Wood ramp {angleDegrees}°: pitch +{angleDegrees:F0}° (−Z high), 90° Y yaw for grain.");
			}
			else
			{
				val.transform.localRotation = val2;
				Plugin.Log.LogInfo((object)$"Wood ramp {angleDegrees}°: pitch +{angleDegrees:F0}° (−Z high).");
			}
			val.transform.localPosition = Vector3.zero;
			val.transform.localScale = Vector3.one;
			EnsureVanillaMaterialsIntact(val);
			LogMaterialSummary(val, angleDegrees, rotateTexture90);
			BuildAngledCollider(prefab, val2);
			BuildSnapPoints(prefab, val2, angleDegrees);
			WearNTearHelper.ConfigureAndRefresh(prefab);
			PhysicsMaterialHelper.ApplyToObject(prefab);
		}

		private static void StripColliders(GameObject prefab)
		{
			Collider[] componentsInChildren = prefab.GetComponentsInChildren<Collider>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren[i]);
			}
		}

		private static void StripChildWearNTear(GameObject prefab)
		{
			WearNTear[] componentsInChildren = prefab.GetComponentsInChildren<WearNTear>(true);
			foreach (WearNTear val in componentsInChildren)
			{
				if ((Object)(object)val != (Object)null && (Object)(object)((Component)val).gameObject != (Object)(object)prefab)
				{
					Object.DestroyImmediate((Object)(object)val);
				}
			}
		}

		private static void ClearSnapPointChildren(GameObject prefab)
		{
			List<GameObject> list = new List<GameObject>();
			for (int i = 0; i < prefab.transform.childCount; i++)
			{
				Transform child = prefab.transform.GetChild(i);
				if (!((Object)(object)child == (Object)null) && (((Object)child).name.StartsWith("snap_", StringComparison.Ordinal) || ((Object)child).name.StartsWith("$hud_snappoint", StringComparison.Ordinal) || ((Component)child).CompareTag("snappoint")))
				{
					list.Add(((Component)child).gameObject);
				}
			}
			Transform[] componentsInChildren = prefab.GetComponentsInChildren<Transform>(true);
			foreach (Transform val in componentsInChildren)
			{
				if ((Object)(object)val == (Object)null || (Object)(object)val == (Object)(object)prefab.transform)
				{
					continue;
				}
				try
				{
					if (((Component)val).CompareTag("snappoint"))
					{
						list.Add(((Component)val).gameObject);
					}
				}
				catch
				{
				}
			}
			foreach (GameObject item in list)
			{
				if ((Object)(object)item != (Object)null)
				{
					Object.DestroyImmediate((Object)(object)item);
				}
			}
		}

		private static void EnsureVanillaMaterialsIntact(GameObject visualRoot)
		{
			if ((Object)(object)visualRoot == (Object)null)
			{
				return;
			}
			MeshRenderer[] componentsInChildren = visualRoot.GetComponentsInChildren<MeshRenderer>(true);
			if (componentsInChildren == null || componentsInChildren.Length == 0)
			{
				Plugin.Log.LogWarning((object)"Angled floor has no MeshRenderers after clone.");
				return;
			}
			bool flag = false;
			MeshRenderer[] array = componentsInChildren;
			foreach (MeshRenderer val in array)
			{
				if (!((Object)(object)val == (Object)null))
				{
					Material[] sharedMaterials = ((Renderer)val).sharedMaterials;
					if (sharedMaterials == null || sharedMaterials.Length == 0 || HasNullMaterial(sharedMaterials))
					{
						flag = true;
						break;
					}
				}
			}
			if (!flag)
			{
				return;
			}
			Material[][] array2 = CaptureVanillaWoodFloorMaterials();
			if (array2 == null || array2.Length == 0)
			{
				Plugin.Log.LogWarning((object)"Could not capture wood_floor materials from a live probe; leaving clone materials as-is.");
				return;
			}
			int num = Mathf.Min(componentsInChildren.Length, array2.Length);
			for (int j = 0; j < num; j++)
			{
				if ((Object)(object)componentsInChildren[j] != (Object)null && array2[j] != null && array2[j].Length != 0)
				{
					((Renderer)componentsInChildren[j]).sharedMaterials = array2[j];
					((Renderer)componentsInChildren[j]).SetPropertyBlock((MaterialPropertyBlock)null);
				}
			}
			Plugin.Log.LogInfo((object)$"Copied wood_floor materials onto {num} MeshRenderer(s).");
		}

		private static bool HasNullMaterial(Material[] mats)
		{
			for (int i = 0; i < mats.Length; i++)
			{
				if ((Object)(object)mats[i] == (Object)null)
				{
					return true;
				}
			}
			return false;
		}

		private static Material[][] CaptureVanillaWoodFloorMaterials()
		{
			GameObject val = null;
			try
			{
				val = ((PrefabManager.Instance != null) ? PrefabManager.Instance.GetPrefab("wood_floor") : null);
			}
			catch
			{
				val = null;
			}
			if ((Object)(object)val == (Object)null && (Object)(object)ZNetScene.instance != (Object)null)
			{
				val = ZNetScene.instance.GetPrefab("wood_floor");
			}
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			Material[][] array = CollectRendererMaterials(val, requireNonNull: true);
			if (array != null && array.Length != 0)
			{
				return array;
			}
			GameObject val2 = null;
			try
			{
				val2 = Object.Instantiate<GameObject>(val);
				((Object)val2).name = "WoodRamps_MatProbe_wood_floor";
				((Object)val2).hideFlags = (HideFlags)61;
				val2.SetActive(true);
				ZNetView component = val2.GetComponent<ZNetView>();
				if ((Object)(object)component != (Object)null)
				{
					((Behaviour)component).enabled = false;
				}
				return CollectRendererMaterials(val2, requireNonNull: true);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("wood_floor material probe failed: " + ex.Message));
				return null;
			}
			finally
			{
				if ((Object)(object)val2 != (Object)null)
				{
					Object.DestroyImmediate((Object)(object)val2);
				}
			}
		}

		private static Material[][] CollectRendererMaterials(GameObject root, bool requireNonNull)
		{
			if ((Object)(object)root == (Object)null)
			{
				return null;
			}
			WearNTear component = root.GetComponent<WearNTear>();
			if ((Object)(object)component != (Object)null && (Object)(object)component.m_new != (Object)null)
			{
				Material[][] array = CollectRendererMaterialsOn(component.m_new, requireNonNull);
				if (array != null && array.Length != 0)
				{
					return array;
				}
			}
			return CollectRendererMaterialsOn(root, requireNonNull);
		}

		private static Material[][] CollectRendererMaterialsOn(GameObject root, bool requireNonNull)
		{
			List<Material[]> list = new List<Material[]>();
			MeshRenderer[] componentsInChildren = root.GetComponentsInChildren<MeshRenderer>(true);
			foreach (MeshRenderer val in componentsInChildren)
			{
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				string text = ((Object)((Component)val).transform).name ?? string.Empty;
				if (text.IndexOf("worn", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("broken", StringComparison.OrdinalIgnoreCase) >= 0)
				{
					continue;
				}
				Material[] sharedMaterials = ((Renderer)val).sharedMaterials;
				if (sharedMaterials != null && sharedMaterials.Length != 0 && (!requireNonNull || !HasNullMaterial(sharedMaterials)))
				{
					Material[] array = (Material[])(object)new Material[sharedMaterials.Length];
					for (int j = 0; j < sharedMaterials.Length; j++)
					{
						array[j] = sharedMaterials[j];
					}
					list.Add(array);
				}
			}
			if (list.Count <= 0)
			{
				return null;
			}
			return list.ToArray();
		}

		private static void LogMaterialSummary(GameObject visualRoot, float angleDegrees, bool rotateTexture90)
		{
			if ((Object)(object)visualRoot == (Object)null)
			{
				return;
			}
			int num = 0;
			int num2 = 0;
			string text = "(none)";
			string text2 = "(none)";
			MeshRenderer[] componentsInChildren = visualRoot.GetComponentsInChildren<MeshRenderer>(true);
			foreach (MeshRenderer val in componentsInChildren)
			{
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				num++;
				Material[] sharedMaterials = ((Renderer)val).sharedMaterials;
				if (sharedMaterials == null)
				{
					continue;
				}
				Material[] array = sharedMaterials;
				foreach (Material val2 in array)
				{
					if (!((Object)(object)val2 == (Object)null))
					{
						num2++;
						if (text == "(none)")
						{
							text = ((Object)val2).name;
							text2 = (((Object)(object)val2.shader != (Object)null) ? ((Object)val2.shader).name : "(null shader)");
						}
					}
				}
			}
			string text3 = (rotateTexture90 ? ", plank yaw 90°" : string.Empty);
			Plugin.Log.LogInfo((object)($"Wood floor {angleDegrees}° visuals{text3}: {num} MeshRenderer(s), {num2} material(s), " + "first='" + text + "' shader='" + text2 + "'."));
		}

		private static void BuildAngledCollider(GameObject prefab, Quaternion pitch)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			float num = 0.06f;
			GameObject val = new GameObject("FloorCollider");
			val.transform.SetParent(prefab.transform, false);
			val.transform.localPosition = Vector3.zero;
			val.transform.localRotation = pitch;
			val.transform.localScale = Vector3.one;
			val.layer = prefab.layer;
			try
			{
				val.tag = "leaky";
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Failed to tag FloorCollider as leaky: " + ex.Message));
			}
			BoxCollider obj = val.AddComponent<BoxCollider>();
			obj.size = new Vector3(2f, 0.12f, 2f);
			obj.center = new Vector3(0f, 0f - num, 0f);
		}

		private static void BuildSnapPoints(GameObject prefab, Quaternion pitch, float angleDegrees)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: 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_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: 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)
			float num = 1f;
			int snapCount = 0;
			AddSnap("$hud_snappoint_top 1", SnapRole.End.High, SnapRole.Lateral.L, new Vector3(num, 0f, 0f - num));
			AddSnap("$hud_snappoint_top 2", SnapRole.End.High, SnapRole.Lateral.R, new Vector3(0f - num, 0f, 0f - num));
			AddSnap("$hud_snappoint_bottom 1", SnapRole.End.Low, SnapRole.Lateral.L, new Vector3(num, 0f, num));
			AddSnap("$hud_snappoint_bottom 2", SnapRole.End.Low, SnapRole.Lateral.R, new Vector3(0f - num, 0f, num));
			Plugin.Log.LogInfo((object)$"Built {snapCount} corner snappoints for {angleDegrees:F0}° ramp (thatch HUD names).");
			void AddSnap(string hudName, SnapRole.End end, SnapRole.Lateral lateral, Vector3 unrotatedLocal)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0007: Expected O, but got Unknown
				//IL_0027: 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_002d: 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_004d: Unknown result type (might be due to invalid IL or missing references)
				GameObject val = new GameObject(hudName);
				val.transform.SetParent(prefab.transform, false);
				val.transform.localPosition = pitch * unrotatedLocal;
				val.transform.localRotation = Quaternion.identity;
				val.transform.localScale = Vector3.one;
				SnapRole snapRole = val.AddComponent<SnapRole>();
				snapRole.SlopeEnd = end;
				snapRole.Side = lateral;
				try
				{
					val.tag = "snappoint";
					snapCount++;
				}
				catch (Exception ex)
				{
					Plugin.Log.LogWarning((object)("Failed to tag snappoint: " + ex.Message));
				}
			}
		}

		private static void FinalizePiece(GameObject prefab, string tokenName, string tokenDescription)
		{
			Piece component = prefab.GetComponent<Piece>();
			if ((Object)(object)component != (Object)null)
			{
				component.m_name = tokenName;
				component.m_description = tokenDescription;
				component.m_groundPiece = false;
				component.m_groundOnly = false;
				component.m_cultivatedGroundOnly = false;
				component.m_vegetationGroundOnly = false;
				component.m_waterPiece = false;
				component.m_noInWater = false;
				component.m_notOnTiltingSurface = false;
				component.m_notOnFloor = false;
				component.m_notOnWood = false;
				component.m_allowAltGroundPlacement = true;
				component.m_canBeRemoved = true;
				component.m_clipGround = false;
				component.m_clipEverything = false;
				object craftingStation;
				if (!ConfigManager.RequireWorkbench.Value)
				{
					craftingStation = null;
				}
				else
				{
					PrefabManager instance = PrefabManager.Instance;
					if (instance == null)
					{
						craftingStation = null;
					}
					else
					{
						GameObject prefab2 = instance.GetPrefab("piece_workbench");
						craftingStation = ((prefab2 != null) ? prefab2.GetComponent<CraftingStation>() : null);
					}
				}
				component.m_craftingStation = (CraftingStation)craftingStation;
			}
			WearNTearHelper.ConfigureAndRefresh(prefab);
			ZNetView component2 = prefab.GetComponent<ZNetView>();
			if ((Object)(object)component2 != (Object)null)
			{
				component2.m_persistent = true;
			}
		}
	}
	internal static class IconHelper
	{
		private static Sprite _fallbackWoodFloorIcon;

		private static bool _fallbackResolved;

		private static readonly object RenderLock = new object();

		private static readonly Dictionary<int, Sprite> IconsByAngle = new Dictionary<int, Sprite>();

		internal static Sprite CreateAngledPieceIcon(GameObject prefab, float angleDegrees, bool rotateTexture90, string nameHint)
		{
			try
			{
				Sprite val = TryLoadPngOverride(angleDegrees, rotateTexture90, nameHint);
				if ((Object)(object)val != (Object)null)
				{
					return val;
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("PNG icon load failed for '" + nameHint + "': " + ex.Message));
			}
			if ((Object)(object)prefab == (Object)null)
			{
				return GetFallbackWoodFloorIcon();
			}
			lock (RenderLock)
			{
				int num = Mathf.RoundToInt(angleDegrees);
				if (rotateTexture90 && IconsByAngle.TryGetValue(num, out var value) && (Object)(object)value != (Object)null)
				{
					Plugin.Log.LogInfo((object)($"Icon '{nameHint}': reuse {num}° sprite (rot90 icon matches " + "non-rot; world FloorVisual yaw unchanged)."));
					return value;
				}
				Sprite val2 = RenderTopDeckIcon(prefab, angleDegrees, nameHint);
				if ((Object)(object)val2 != (Object)null && !IconsByAngle.ContainsKey(num))
				{
					IconsByAngle[num] = val2;
				}
				return val2;
			}
		}

		private static Sprite RenderTopDeckIcon(GameObject prefab, float angleDegrees, string nameHint)
		{
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Expected O, but got Unknown
			GameObject val = null;
			try
			{
				val = BuildIconOnlyClone(prefab);
				if ((Object)(object)val == (Object)null)
				{
					Plugin.Log.LogWarning((object)("Icon clone failed for '" + nameHint + "'; using fallback."));
					return GetFallbackWoodFloorIcon();
				}
				Transform val2 = val.transform.Find("FloorVisual");
				if ((Object)(object)val2 == (Object)null)
				{
					Plugin.Log.LogWarning((object)("Icon visual missing for '" + nameHint + "'; using fallback."));
					return GetFallbackWoodFloorIcon();
				}
				val2.localPosition = Vector3.zero;
				val2.localScale = Vector3.one;
				val2.localRotation = Quaternion.Euler(0f - angleDegrees, 0f, 0f);
				Plugin.Log.LogInfo((object)($"Icon '{nameHint}': capture visual pitch={angleDegrees}°, yaw=0 " + "(icon-only; world prefab grain untouched)."));
				Quaternion rotation = RenderManager.IsometricRotation * Quaternion.Euler(angleDegrees * 0.5f, 0f, 0f) * Quaternion.Euler(0f, 180f, 0f);
				float num = ((Mathf.Abs(angleDegrees - 45f) < 0.1f) ? 0.58f : 0.64f);
				RenderRequest val3 = new RenderRequest(val)
				{
					Rotation = rotation,
					Width = 512,
					Height = 512,
					DistanceMultiplier = num,
					FieldOfView = 0.5f,
					ParticleSimulationTime = -1f,
					UseCache = false
				};
				Sprite val4 = RenderManager.Instance.Render(val3);
				if ((Object)(object)val4 == (Object)null)
				{
					Plugin.Log.LogWarning((object)("RenderManager null for '" + nameHint + "'; using fallback."));
					return GetFallbackWoodFloorIcon();
				}
				if (!string.IsNullOrEmpty(nameHint))
				{
					((Object)val4).name = nameHint;
				}
				Plugin.Log.LogInfo((object)("Rendered inclined top-deck icon '" + nameHint + "' " + $"(pitch={angleDegrees}°, iconYaw=0, " + $"cam=Iso*Euler({angleDegrees * 0.5f:0.#},0,0)*Y180, " + $"dist×={num}, {512}px)."));
				return val4;
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Icon render failed for '" + nameHint + "': " + ex.Message));
				return GetFallbackWoodFloorIcon();
			}
			finally
			{
				if ((Object)(object)val != (Object)null)
				{
					try
					{
						Object.DestroyImmediate((Object)(object)val);
					}
					catch
					{
					}
				}
			}
		}

		private static Sprite TryLoadPngOverride(float angleDegrees, bool rotateTexture90, string nameHint)
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Expected O, but got Unknown
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			string text = BuildPngFileName(angleDegrees, rotateTexture90);
			if (string.IsNullOrEmpty(text))
			{
				return null;
			}
			string iconsDirectory = GetIconsDirectory();
			if (string.IsNullOrEmpty(iconsDirectory))
			{
				return null;
			}
			string text2 = Path.Combine(iconsDirectory, text);
			if (!File.Exists(text2))
			{
				return null;
			}
			byte[] array = File.ReadAllBytes(text2);
			if (array == null || array.Length == 0)
			{
				return null;
			}
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
			if (!TryLoadPngBytes(val, array))
			{
				Object.Destroy((Object)(object)val);
				Plugin.Log.LogWarning((object)("PNG override unreadable: " + text2));
				return null;
			}
			((Object)val).name = nameHint ?? Path.GetFileNameWithoutExtension(text);
			((Texture)val).filterMode = (FilterMode)1;
			((Texture)val).wrapMode = (TextureWrapMode)1;
			Sprite obj = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f);
			((Object)obj).name = ((Object)val).name;
			Plugin.Log.LogInfo((object)$"Loaded custom icon PNG '{text2}' ({((Texture)val).width}x{((Texture)val).height}).");
			return obj;
		}

		private static bool TryLoadPngBytes(Texture2D texture, byte[] pngBytes)
		{
			try
			{
				Type type = Type.GetType("UnityEngine.ImageConversion, UnityEngine.ImageConversionModule");
				if (type != null)
				{
					MethodInfo method = type.GetMethod("LoadImage", BindingFlags.Static | BindingFlags.Public, null, new Type[2]
					{
						typeof(Texture2D),
						typeof(byte[])
					}, null);
					if (method != null)
					{
						return (bool)method.Invoke(null, new object[2] { texture, pngBytes });
					}
				}
				MethodInfo method2 = typeof(Texture2D).GetMethod("LoadImage", BindingFlags.Instance | BindingFlags.Public, null, new Type[1] { typeof(byte[]) }, null);
				if (method2 != null)
				{
					return (bool)method2.Invoke(texture, new object[1] { pngBytes });
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("PNG decode failed: " + ex.Message));
			}
			return false;
		}

		private static string BuildPngFileName(float angleDegrees, bool rotateTexture90)
		{
			string text = ((Mathf.RoundToInt(angleDegrees) == 45) ? "wood_floor_45" : "wood_floor_26");
			if (!rotateTexture90)
			{
				return text + ".png";
			}
			return text + "_rot90.png";
		}

		private static string GetIconsDirectory()
		{
			try
			{
				if ((Object)(object)Plugin.Instance != (Object)null)
				{
					string location = ((BaseUnityPlugin)Plugin.Instance).Info.Location;
					if (!string.IsNullOrEmpty(location))
					{
						return Path.Combine(Path.GetDirectoryName(location) ?? string.Empty, "icons");
					}
				}
			}
			catch
			{
			}
			try
			{
				string pluginPath = Paths.PluginPath;
				if (!string.IsNullOrEmpty(pluginPath))
				{
					return Path.Combine(pluginPath, "ModdedWolf-WoodRamps", "icons");
				}
			}
			catch
			{
			}
			return null;
		}

		private static GameObject BuildIconOnlyClone(GameObject prefab)
		{
			//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_0040: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = Object.Instantiate<GameObject>(prefab);
			((Object)val).name = ((Object)prefab).name + "_IconOnly";
			((Object)val).hideFlags = (HideFlags)61;
			val.transform.SetPositionAndRotation(Vector3.zero, Quaternion.identity);
			val.transform.localScale = Vector3.one;
			Component[] componentsInChildren = val.GetComponentsInChildren<Component>(true);
			foreach (Component val2 in componentsInChildren)
			{
				if (!((Object)(object)val2 == (Object)null) && !(val2 is Transform) && !(val2 is MeshFilter) && !(val2 is MeshRenderer) && !(val2 is SkinnedMeshRenderer))
				{
					try
					{
						Object.DestroyImmediate((Object)(object)val2);
					}
					catch
					{
					}
				}
			}
			Transform val3 = val.transform.Find("FloorVisual");
			if ((Object)(object)val3 == (Object)null)
			{
				Object.DestroyImmediate((Object)(object)val);
				return null;
			}
			List<GameObject> list = new List<GameObject>();
			for (int j = 0; j < val.transform.childCount; j++)
			{
				Transform child = val.transform.GetChild(j);
				if ((Object)(object)child != (Object)null && (Object)(object)child != (Object)(object)val3)
				{
					list.Add(((Component)child).gameObject);
				}
			}
			Transform[] componentsInChildren2 = ((Component)val3).GetComponentsInChildren<Transform>(true);
			foreach (Transform val4 in componentsInChildren2)
			{
				if (!((Object)(object)val4 == (Object)null) && !((Object)(object)val4 == (Object)(object)val3))
				{
					string text = ((Object)val4).name ?? string.Empty;
					if (text.IndexOf("worn", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("broken", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("damage", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("lod1", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("lod2", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("lod3", StringComparison.OrdinalIgnoreCase) >= 0 || text.Equals("wet", StringComparison.OrdinalIgnoreCase) || text.StartsWith("wet", StringComparison.OrdinalIgnoreCase))
					{
						list.Add(((Component)val4).gameObject);
					}
				}
			}
			foreach (GameObject item in list)
			{
				if ((Object)(object)item != (Object)null)
				{
					Object.DestroyImmediate((Object)(object)item);
				}
			}
			MeshRenderer[] componentsInChildren3 = ((Component)val3).GetComponentsInChildren<MeshRenderer>(true);
			if (componentsInChildren3 == null || componentsInChildren3.Length == 0)
			{
				Object.DestroyImmediate((Object)(object)val);
				return null;
			}
			MeshRenderer[] array = componentsInChildren3;
			foreach (MeshRenderer val5 in array)
			{
				if ((Object)(object)val5 != (Object)null)
				{
					((Renderer)val5).enabled = true;
					((Component)val5).gameObject.SetActive(true);
				}
			}
			val.SetActive(true);
			return val;
		}

		private static Sprite GetFallbackWoodFloorIcon()
		{
			if (_fallbackResolved)
			{
				return _fallbackWoodFloorIcon;
			}
			_fallbackResolved = true;
			try
			{
				GameObject val = ((PrefabManager.Instance != null) ? PrefabManager.Instance.GetPrefab("wood_floor") : null);
				if ((Object)(object)val == (Object)null && (Object)(object)ZNetScene.instance != (Object)null)
				{
					val = ZNetScene.instance.GetPrefab("wood_floor");
				}
				Piece val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<Piece>() : null);
				_fallbackWoodFloorIcon = (((Object)(object)val2 != (Object)null) ? val2.m_icon : null);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Fallback wood_floor icon failed: " + ex.Message));
				_fallbackWoodFloorIcon = null;
			}
			return _fallbackWoodFloorIcon;
		}
	}
	internal static class PhysicsMaterialHelper
	{
		private static PhysicsMaterial _sledMaterial;

		internal static PhysicsMaterial GetOrCreate()
		{
			//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_002d: 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_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Expected O, but got Unknown
			if ((Object)(object)_sledMaterial != (Object)null)
			{
				return _sledMaterial;
			}
			_sledMaterial = new PhysicsMaterial("WoodRamps_LowFriction")
			{
				dynamicFriction = ConfigManager.DynamicFriction.Value,
				staticFriction = ConfigManager.StaticFriction.Value,
				bounciness = 0f,
				frictionCombine = (PhysicsMaterialCombine)2,
				bounceCombine = (PhysicsMaterialCombine)2
			};
			return _sledMaterial;
		}

		internal static void ApplyToObject(GameObject go)
		{
			if ((Object)(object)go == (Object)null)
			{
				return;
			}
			PhysicsMaterial orCreate = GetOrCreate();
			Collider[] componentsInChildren = go.GetComponentsInChildren<Collider>(true);
			foreach (Collider val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null) && !val.isTrigger)
				{
					val.material = orCreate;
				}
			}
		}
	}
	internal static class PieceRegistration
	{
		internal const string Piece26Name = "piece_wood_floor_26";

		internal const string Piece45Name = "piece_wood_floor_45";

		internal const string Piece26Rot90Name = "piece_wood_floor_26_rot90";

		internal const string Piece45Rot90Name = "piece_wood_floor_45_rot90";

		internal const string Token26Name = "$woodramps_ramp26_name";

		internal const string Token26Description = "$woodramps_ramp26_description";

		internal const string Token45Name = "$woodramps_ramp45_name";

		internal const string Token45Description = "$woodramps_ramp45_description";

		internal const string Token26Rot90Name = "$woodramps_ramp26_rot90_name";

		internal const string Token26Rot90Description = "$woodramps_ramp26_rot90_description";

		internal const string Token45Rot90Name = "$woodramps_ramp45_rot90_name";

		internal const string Token45Rot90Description = "$woodramps_ramp45_rot90_description";

		private static bool _registered;

		internal static void Register()
		{
			CustomLocalization localization = LocalizationManager.Instance.GetLocalization();
			string text = "English";
			string text2 = "$woodramps_ramp26_name";
			localization.AddTranslation(ref text, ref text2, "Wood Ramp 26°");
			text = "English";
			text2 = "$woodramps_ramp26_description";
			localization.AddTranslation(ref text, ref text2, "A wood ramp angled at 26 degrees. Matches vanilla 26° beam slopes — great for Shield Sledding runs.");
			text = "English";
			text2 = "$woodramps_ramp45_name";
			localization.AddTranslation(ref text, ref text2, "Wood Ramp 45°");
			text = "English";
			text2 = "$woodramps_ramp45_description";
			localization.AddTranslation(ref text, ref text2, "A wood ramp angled at 45 degrees. Matches vanilla 45° beam slopes — great for Shield Sledding runs.");
			text = "English";
			text2 = "$woodramps_ramp26_rot90_name";
			localization.AddTranslation(ref text, ref text2, "Wood Ramp 26° (Rotated)");
			text = "English";
			text2 = "$woodramps_ramp26_rot90_description";
			localization.AddTranslation(ref text, ref text2, "A wood ramp angled at 26 degrees with plank grain rotated 90°. Same slope as Wood Ramp 26°.");
			text = "English";
			text2 = "$woodramps_ramp45_rot90_name";
			localization.AddTranslation(ref text, ref text2, "Wood Ramp 45° (Rotated)");
			text = "English";
			text2 = "$woodramps_ramp45_rot90_description";
			localization.AddTranslation(ref text, ref text2, "A wood ramp angled at 45 degrees with plank grain rotated 90°. Same slope as Wood Ramp 45°.");
			PrefabManager.OnVanillaPrefabsAvailable += OnVanillaPrefabsAvailable;
		}

		internal static void Unregister()
		{
			PrefabManager.OnVanillaPrefabsAvailable -= OnVanillaPrefabsAvailable;
		}

		private static void OnVanillaPrefabsAvailable()
		{
			if (_registered)
			{
				return;
			}
			try
			{
				bool num = RegisterFloor("piece_wood_floor_26", 26f, rotateTexture90: false, "$woodramps_ramp26_name", "$woodramps_ramp26_description");
				bool flag = RegisterFloor("piece_wood_floor_45", 45f, rotateTexture90: false, "$woodramps_ramp45_name", "$woodramps_ramp45_description");
				bool flag2 = RegisterFloor("piece_wood_floor_26_rot90", 26f, rotateTexture90: true, "$woodramps_ramp26_rot90_name", "$woodramps_ramp26_rot90_description");
				bool flag3 = RegisterFloor("piece_wood_floor_45_rot90", 45f, rotateTexture90: true, "$woodramps_ramp45_rot90_name", "$woodramps_ramp45_rot90_description");
				if (!num || !flag || !flag2 || !flag3)
				{
					Plugin.Log.LogError((object)"One or more wood ramp pieces failed to register.");
					return;
				}
				_registered = true;
				PrefabManager.OnVanillaPrefabsAvailable -= OnVanillaPrefabsAvailable;
				Plugin.Log.LogInfo((object)"Registered Wood Ramp 26°, 45°, 26° (Rotated), and 45° (Rotated).");
			}
			catch (Exception arg)
			{
				Plugin.Log.LogError((object)$"Failed to register wood ramps: {arg}");
			}
		}

		private static bool RegisterFloor(string pieceName, float angleDegrees, bool rotateTexture90, string tokenName, string tokenDescription)
		{
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Expected O, but got Unknown
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Expected O, but got Unknown
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Expected O, but got Unknown
			GameObject val = FloorPrefabBuilder.CreateAngledFloor(pieceName, angleDegrees, rotateTexture90, tokenName, tokenDescription);
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Log.LogError((object)("Failed to create prefab '" + pieceName + "'."));
				return false;
			}
			Sprite val2 = null;
			try
			{
				val2 = IconHelper.CreateAngledPieceIcon(val, angleDegrees, rotateTexture90, pieceName + "_icon");
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Icon resolve failed for '" + pieceName + "': " + ex.Message));
				val2 = null;
			}
			PieceConfig val3 = new PieceConfig
			{
				Name = tokenName,
				Description = tokenDescription,
				PieceTable = PieceTables.Hammer,
				Category = PieceCategories.Building,
				AllowedInDungeons = false,
				Icon = val2
			};
			if (ConfigManager.RequireWorkbench.Value)
			{
				val3.CraftingStation = CraftingStations.Workbench;
			}
			val3.AddRequirement(new RequirementConfig("Wood", Mathf.Max(1, ConfigManager.WoodCost.Value), 0, true));
			((Object)val).name = pieceName;
			CustomPiece val4 = new CustomPiece(val, false, val3);
			if (!PieceManager.Instance.AddPiece(val4))
			{
				Plugin.Log.LogError((object)("PieceManager rejected " + pieceName + "."));
				return false;
			}
			try
			{
				Piece component = val.GetComponent<Piece>();
				if ((Object)(object)component != (Object)null && (Object)(object)val2 != (Object)null)
				{
					component.m_icon = val2;
				}
			}
			catch (Exception ex2)
			{
				Plugin.Log.LogWarning((object)("Failed to assign m_icon on '" + pieceName + "': " + ex2.Message));
			}
			int stableHashCode = StringExtensionMethods.GetStableHashCode(pieceName);
			string text = (rotateTexture90 ? ", plank yaw 90°" : string.Empty);
			Plugin.Log.LogInfo((object)$"Registered build piece '{pieceName}' at {angleDegrees}°{text} (hash {stableHashCode}).");
			return true;
		}

		internal static bool IsAngledWoodFloor(GameObject go)
		{
			if ((Object)(object)go == (Object)null)
			{
				return false;
			}
			string text = ((Object)go).name.Replace("(Clone)", string.Empty).Trim();
			switch (text)
			{
			default:
				return text == "piece_wood_floor_45_rot90";
			case "piece_wood_floor_26":
			case "piece_wood_floor_45":
			case "piece_wood_floor_26_rot90":
				return true;
			}
		}

		internal static bool IsAngledWoodFloor(Piece piece)
		{
			if ((Object)(object)piece != (Object)null)
			{
				return IsAngledWoodFloor(((Component)piece).gameObject);
			}
			return false;
		}
	}
	[BepInPlugin("ModdedWolf.WoodRamps", "Wood Ramps", "1.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		public const string GUID = "ModdedWolf.WoodRamps";

		public const string NAME = "Wood Ramps";

		public const string VERSION = "1.0.0";

		public const string ShieldSleddingGuid = "ModdedWolf.ShieldSledding";

		internal static Plugin Instance;

		internal static ManualLogSource Log;

		private Harmony _harmony;

		private void Awake()
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			ConfigManager.Init(((BaseUnityPlugin)this).Config);
			PieceRegistration.Register();
			_harmony = new Harmony("ModdedWolf.WoodRamps");
			_harmony.PatchAll(typeof(Plugin).Assembly);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Wood Ramps v1.0.0 loaded (requires ModdedWolf.ShieldSledding).");
		}

		private void OnDestroy()
		{
			PieceRegistration.Unregister();
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			_harmony = null;
		}
	}
	internal sealed class SnapRole : MonoBehaviour
	{
		internal enum End
		{
			Low,
			High,
			Side,
			Mid
		}

		internal enum Lateral
		{
			L,
			C,
			R,
			None
		}

		internal End SlopeEnd;

		internal Lateral Side;

		internal static SnapRole Get(Transform t)
		{
			if (!((Object)(object)t != (Object)null))
			{
				return null;
			}
			return ((Component)t).GetComponent<SnapRole>();
		}
	}
	internal static class WearNTearHelper
	{
		private static readonly FieldInfo CollidersField = typeof(WearNTear).GetField("m_colliders", BindingFlags.Instance | BindingFlags.NonPublic);

		private static readonly FieldInfo BoundsField = typeof(WearNTear).GetField("m_bounds", BindingFlags.Instance | BindingFlags.NonPublic);

		private static readonly FieldInfo RenderersField = typeof(WearNTear).GetField("m_renderers", BindingFlags.Instance | BindingFlags.NonPublic);

		private static bool _copiedWoodDefaults;

		private static float _woodHealth = 400f;

		private static MaterialType _woodMaterial = (MaterialType)0;

		private static bool _woodSupports = true;

		private static bool _woodNoRoofWear = true;

		private static bool _woodNoSupportWear = true;

		private static bool _woodAshDamageImmune = false;

		private static bool _woodBurnable = true;

		private static DamageModifiers _woodDamages;

		private static bool _copiedDamages;

		private static EffectList _woodDestroyedEffect;

		private static EffectList _woodHitEffect;

		private static EffectList _woodSwitchEffect;

		private static bool _copiedEffects;

		internal static void ConfigureAndRefresh(GameObject root)
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)root == (Object)null)
			{
				return;
			}
			WearNTear[] componentsInChildren = root.GetComponentsInChildren<WearNTear>(true);
			foreach (WearNTear val in componentsInChildren)
			{
				if ((Object)(object)val != (Object)null && (Object)(object)((Component)val).gameObject != (Object)(object)root)
				{
					Object.DestroyImmediate((Object)(object)val);
				}
			}
			WearNTear component = root.GetComponent<WearNTear>();
			if ((Object)(object)component == (Object)null)
			{
				ClearPropertyBlocks(root);
				return;
			}
			EnsureWoodDefaultsCached();
			component.m_materialType = _woodMaterial;
			component.m_health = ((_woodHealth > 0f) ? _woodHealth : 400f);
			component.m_supports = _woodSupports;
			component.m_noRoofWear = true;
			component.m_noSupportWear = _woodNoSupportWear;
			component.m_ashDamageImmune = _woodAshDamageImmune;
			component.m_burnable = _woodBurnable;
			component.m_forceCorrectCOMCalculation = true;
			component.m_autoCreateFragments = true;
			if (_copiedDamages)
			{
				component.m_damages = _woodDamages;
			}
			if (_copiedEffects)
			{
				if (_woodDestroyedEffect != null)
				{
					component.m_destroyedEffect = _woodDestroyedEffect;
				}
				if (_woodHitEffect != null)
				{
					component.m_hitEffect = _woodHitEffect;
				}
				if (_woodSwitchEffect != null)
				{
					component.m_switchEffect = _woodSwitchEffect;
				}
			}
			component.m_fragmentRoots = null;
			if (!IsAlive(component.m_wet))
			{
				Transform val2 = FindChildRecursive(root.transform, "wet");
				component.m_wet = (((Object)(object)val2 != (Object)null) ? ((Component)val2).gameObject : null);
			}
			if (!IsAlive(component.m_new) || !IsAlive(component.m_worn) || !IsAlive(component.m_broken))
			{
				Transform val3 = root.transform.Find("FloorVisual");
				GameObject val4 = (((Object)(object)val3 != (Object)null) ? ((Component)val3).gameObject : null);
				if (!IsAlive(component.m_new))
				{
					component.m_new = val4;
				}
				if (!IsAlive(component.m_worn))
				{
					component.m_worn = val4;
				}
				if (!IsAlive(component.m_broken))
				{
					component.m_broken = val4;
				}
			}
			if (RenderersField != null && RenderersField.GetValue(component) is IList list)
			{
				list.Clear();
				Transform val5 = root.transform.Find("FloorVisual");
				Renderer[] componentsInChildren2 = ((Component)(((Object)(object)val5 != (Object)null) ? val5 : root.transform)).GetComponentsInChildren<Renderer>(true);
				foreach (Renderer val6 in componentsInChildren2)
				{
					if ((Object)(object)val6 != (Object)null)
					{
						list.Add(val6);
					}
				}
			}
			if (CollidersField != null)
			{
				CollidersField.SetValue(component, null);
			}
			if (BoundsField != null)
			{
				if (BoundsField.GetValue(component) is IList list2)
				{
					list2.Clear();
				}
				else
				{
					BoundsField.SetValue(component, null);
				}
			}
			try
			{
				component.SetupColliders();
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("WearNTear.SetupColliders failed: " + ex.Message));
			}
			component.m_clearCachedSupport = false;
			try
			{
				component.SetHealthVisual(1f, false);
			}
			catch (Exception ex2)
			{
				Plugin.Log.LogWarning((object)("WearNTear.SetHealthVisual failed: " + ex2.Message));
			}
			ClearPropertyBlocks(root);
		}

		private static bool IsAlive(GameObject go)
		{
			return (Object)(object)go != (Object)null;
		}

		private static Transform FindChildRecursive(Transform root, string name)
		{
			if ((Object)(object)root == (Object)null || string.IsNullOrEmpty(name))
			{
				return null;
			}
			for (int i = 0; i < root.childCount; i++)
			{
				Transform child = root.GetChild(i);
				if (!((Object)(object)child == (Object)null))
				{
					if (string.Equals(((Object)child).name, name, StringComparison.OrdinalIgnoreCase))
					{
						return child;
					}
					Transform val = FindChildRecursive(child, name);
					if ((Object)(object)val != (Object)null)
					{
						return val;
					}
				}
			}
			return null;
		}

		internal static void ClearPropertyBlocks(GameObject root)
		{
			if ((Object)(object)root == (Object)null)
			{
				return;
			}
			Transform val = root.transform.Find("FloorVisual");
			MeshRenderer[] componentsInChildren = ((Component)(((Object)(object)val != (Object)null) ? val : root.transform)).GetComponentsInChildren<MeshRenderer>(true);
			foreach (MeshRenderer val2 in componentsInChildren)
			{
				if ((Object)(object)val2 != (Object)null)
				{
					((Renderer)val2).SetPropertyBlock((MaterialPropertyBlock)null);
				}
			}
		}

		private static void EnsureWoodDefaultsCached()
		{
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			if (_copiedWoodDefaults)
			{
				return;
			}
			_copiedWoodDefaults = true;
			GameObject val = null;
			try
			{
				val = ((PrefabManager.Instance != null) ? PrefabManager.Instance.GetPrefab("wood_floor") : null);
			}
			catch
			{
				val = null;
			}
			if ((Object)(object)val == (Object)null && (Object)(object)ZNetScene.instance != (Object)null)
			{
				val = ZNetScene.instance.GetPrefab("wood_floor");
			}
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			WearNTear component = val.GetComponent<WearNTear>();
			if ((Object)(object)component == (Object)null)
			{
				return;
			}
			_woodHealth = ((component.m_health > 0f) ? component.m_health : 400f);
			_woodMaterial = component.m_materialType;
			_woodSupports = component.m_supports;
			_woodNoRoofWear = component.m_noRoofWear;
			_woodNoSupportWear = component.m_noSupportWear;
			_woodAshDamageImmune = component.m_ashDamageImmune;
			_woodBurnable = component.m_burnable;
			try
			{
				_woodDamages = component.m_damages;
				_copiedDamages = true;
			}
			catch
			{
				_copiedDamages = false;
			}
			try
			{
				_woodDestroyedEffect = component.m_destroyedEffect;
				_woodHitEffect = component.m_hitEffect;
				_woodSwitchEffect = component.m_switchEffect;
				_copiedEffects = true;
			}
			catch
			{
				_copiedEffects = false;
			}
		}
	}
}
namespace WoodFloors2645.Patches
{
	[HarmonyPatch(typeof(Player), "FindClosestSnapPoints")]
	internal static class SnapPreferPatch
	{
		private static readonly List<Transform> GhostSnaps = new List<Transform>(8);

		private static readonly List<Transform> WorldSnaps = new List<Transform>(64);

		private static bool Prefix(Transform ghost, float maxSnapDistance, ref Transform a, ref Transform b, List<Piece> pieces, ref bool __result)
		{
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if ((Object)(object)ghost == (Object)null)
				{
					return true;
				}
				Piece component = ((Component)ghost).GetComponent<Piece>();
				if (!PieceRegistration.IsAngledWoodFloor(component))
				{
					return true;
				}
				GhostSnaps.Clear();
				component.GetSnapPoints(GhostSnaps);
				if (GhostSnaps.Count == 0)
				{
					return true;
				}
				if (pieces == null)
				{
					return true;
				}
				WorldSnaps.Clear();
				pieces.Clear();
				Piece.GetSnapPoints(ghost.position, 10f, WorldSnaps, pieces);
				if (WorldSnaps.Count == 0)
				{
					return true;
				}
				Transform val = null;
				Transform val2 = null;
				float num = float.MaxValue;
				for (int i = 0; i < GhostSnaps.Count; i++)
				{
					Transform val3 = GhostSnaps[i];
					if ((Object)(object)val3 == (Object)null)
					{
						continue;
					}
					SnapRole snapRole = SnapRole.Get(val3);
					for (int j = 0; j < WorldSnaps.Count; j++)
					{
						Transform val4 = WorldSnaps[j];
						if ((Object)(object)val4 == (Object)null)
						{
							continue;
						}
						Piece componentInParent = ((Component)val4).GetComponentInParent<Piece>();
						if ((Object)(object)componentInParent == (Object)null || (Object)(object)componentInParent == (Object)(object)component)
						{
							continue;
						}
						float num2 = Vector3.Distance(val3.position, val4.position);
						if (num2 > maxSnapDistance)
						{
							continue;
						}
						SnapRole snapRole2 = SnapRole.Get(val4);
						float num3 = num2;
						if (PieceRegistration.IsAngledWoodFloor(componentInParent) && (Object)(object)snapRole != (Object)null && (Object)(object)snapRole2 != (Object)null)
						{
							if (snapRole.Side == snapRole2.Side && snapRole.Side != SnapRole.Lateral.None)
							{
								num3 -= 8f;
							}
							else if (snapRole.Side != SnapRole.Lateral.None && snapRole2.Side != SnapRole.Lateral.None)
							{
								num3 += 6f;
							}
							if ((snapRole.SlopeEnd == SnapRole.End.Low && snapRole2.SlopeEnd == SnapRole.End.High) || (snapRole.SlopeEnd == SnapRole.End.High && snapRole2.SlopeEnd == SnapRole.End.Low))
							{
								num3 -= 6f;
							}
							else if (snapRole.SlopeEnd == snapRole2.SlopeEnd && snapRole.SlopeEnd != SnapRole.End.Mid)
							{
								num3 += 4f;
							}
						}
						if (num3 < num)
						{
							num = num3;
							val = val3;
							val2 = val4;
						}
					}
				}
				if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null)
				{
					return true;
				}
				a = val;
				b = val2;
				__result = true;
				return false;
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("SnapPreferPatch fell back to vanilla: " + ex.Message));
				}
				return true;
			}
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}