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 DynamicFriction; internal static ConfigEntry StaticFriction; internal static ConfigEntry WoodCost; internal static ConfigEntry RequireWorkbench; internal static void Init(ConfigFile config) { DynamicFriction = config.Bind("Physics", "DynamicFriction", 0.05f, "Dynamic friction on the angled wood ramps (lower = better for Shield Sledding)."); StaticFriction = config.Bind("Physics", "StaticFriction", 0.05f, "Static friction on the angled wood ramps."); WoodCost = config.Bind("Building", "WoodCost", 2, "Wood required to place each wood ramp piece (vanilla wood floor is 2)."); RequireWorkbench = config.Bind("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 list = new List(); 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(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(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 list = new List(); 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(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(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(val); ((Object)val2).name = "WoodRamps_MatProbe_wood_floor"; ((Object)val2).hideFlags = (HideFlags)61; val2.SetActive(true); ZNetView component = val2.GetComponent(); 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(); 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 list = new List(); MeshRenderer[] componentsInChildren = root.GetComponentsInChildren(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(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(); 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.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(); 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() : null); } } component.m_craftingStation = (CraftingStation)craftingStation; } WearNTearHelper.ConfigureAndRefresh(prefab); ZNetView component2 = prefab.GetComponent(); 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 IconsByAngle = new Dictionary(); 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(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(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 list = new List(); 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(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(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() : 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(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(); 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(); } } 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(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(); 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(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(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(); 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 GhostSnaps = new List(8); private static readonly List WorldSnaps = new List(64); private static bool Prefix(Transform ghost, float maxSnapDistance, ref Transform a, ref Transform b, List 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(); 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(); 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) { } } }