Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of WoodRamps v1.0.0
WoodRamps.dll
Decompiled 21 hours agousing 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) { } } }