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.1
WoodRamps.dll
Decompiled a month 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.1.0")] [assembly: AssemblyInformationalVersion("1.0.1")] [assembly: AssemblyProduct("WoodRamps")] [assembly: AssemblyTitle("WoodRamps")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.1.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 = more slippery)."); 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 { private sealed class PlankTemplate { internal Mesh Mesh; internal Material[] Materials; internal Quaternion Rotation; internal Vector3 Scale; internal float Y; internal int Layer; } internal const string VisualChildName = "FloorVisual"; internal const string ColliderChildName = "FloorCollider"; internal const float HalfSize = 1f; internal static GameObject CreateAngledFloor(RampVariant variant) { //IL_005b: Unknown result type (might be due to invalid IL or missing references) GameObject val = PrefabManager.Instance.CreateClonedPrefab(variant.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 = variant.PieceName; AngleVanillaFloor(val, variant); FinalizePiece(val, variant.TokenName, variant.TokenDescription); val.transform.localScale = Vector3.one; return val; } private static void AngleVanillaFloor(GameObject prefab, RampVariant variant) { //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Expected O, but got Unknown //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_0193: 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); } } float angleDegrees = variant.AngleDegrees; float slopeLength = variant.SlopeLength; Quaternion val = Quaternion.Euler(angleDegrees, 0f, 0f); GameObject val2 = new GameObject("FloorVisual"); val2.transform.SetParent(prefab.transform, false); val2.transform.localPosition = Vector3.zero; val2.transform.localRotation = val; val2.transform.localScale = Vector3.one; foreach (Transform item in list) { if (!((Object)(object)item == (Object)null) && !((Object)(object)item == (Object)(object)val2.transform)) { item.SetParent(val2.transform, false); } } EnsureVanillaMaterialsIntact(val2); float deckTop = BuildPlankDeck(prefab, variant); string text = (variant.Rotated ? ", planks across slope" : string.Empty); Plugin.Log.LogInfo((object)$"Wood ramp {variant.Label}: pitch {angleDegrees:0.##}° (−Z high), slope {slopeLength:0.###} m{text}."); LogMaterialSummary(val2, angleDegrees, variant.Rotated); BuildAngledCollider(prefab, val, slopeLength, deckTop); BuildSnapPoints(prefab, val, slopeLength, angleDegrees); WearNTearHelper.ConfigureAndRefresh(prefab); PhysicsMaterialHelper.ApplyToObject(prefab); } private static float BuildPlankDeck(GameObject prefab, RampVariant variant) { //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_0422: Unknown result type (might be due to invalid IL or missing references) //IL_0427: Unknown result type (might be due to invalid IL or missing references) //IL_043e: Unknown result type (might be due to invalid IL or missing references) //IL_01ad: Unknown result type (might be due to invalid IL or missing references) //IL_01b3: Unknown result type (might be due to invalid IL or missing references) //IL_01b8: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_01d3: Unknown result type (might be due to invalid IL or missing references) //IL_01d8: Unknown result type (might be due to invalid IL or missing references) //IL_01dd: Unknown result type (might be due to invalid IL or missing references) //IL_02f4: Unknown result type (might be due to invalid IL or missing references) //IL_02f9: Unknown result type (might be due to invalid IL or missing references) //IL_02fd: Unknown result type (might be due to invalid IL or missing references) //IL_0302: Unknown result type (might be due to invalid IL or missing references) //IL_0304: Unknown result type (might be due to invalid IL or missing references) //IL_0309: Unknown result type (might be due to invalid IL or missing references) //IL_030b: Unknown result type (might be due to invalid IL or missing references) //IL_030d: Unknown result type (might be due to invalid IL or missing references) //IL_031e: Unknown result type (might be due to invalid IL or missing references) //IL_0323: Unknown result type (might be due to invalid IL or missing references) //IL_0332: Unknown result type (might be due to invalid IL or missing references) //IL_0339: Unknown result type (might be due to invalid IL or missing references) //IL_0345: Unknown result type (might be due to invalid IL or missing references) //IL_034a: Unknown result type (might be due to invalid IL or missing references) //IL_035a: Unknown result type (might be due to invalid IL or missing references) //IL_0366: Unknown result type (might be due to invalid IL or missing references) //IL_036d: Unknown result type (might be due to invalid IL or missing references) //IL_0372: Unknown result type (might be due to invalid IL or missing references) //IL_038b: Unknown result type (might be due to invalid IL or missing references) //IL_0233: Unknown result type (might be due to invalid IL or missing references) //IL_021e: Unknown result type (might be due to invalid IL or missing references) //IL_0238: Unknown result type (might be due to invalid IL or missing references) //IL_024b: Unknown result type (might be due to invalid IL or missing references) //IL_0250: Unknown result type (might be due to invalid IL or missing references) //IL_025d: Unknown result type (might be due to invalid IL or missing references) //IL_0270: Unknown result type (might be due to invalid IL or missing references) //IL_0276: Unknown result type (might be due to invalid IL or missing references) //IL_0278: Unknown result type (might be due to invalid IL or missing references) //IL_0284: Unknown result type (might be due to invalid IL or missing references) //IL_028b: Unknown result type (might be due to invalid IL or missing references) //IL_0290: Unknown result type (might be due to invalid IL or missing references) //IL_029a: Unknown result type (might be due to invalid IL or missing references) //IL_02a0: Unknown result type (might be due to invalid IL or missing references) //IL_02a7: Unknown result type (might be due to invalid IL or missing references) //IL_02ad: Unknown result type (might be due to invalid IL or missing references) //IL_02b4: Unknown result type (might be due to invalid IL or missing references) WearNTear component = prefab.GetComponent<WearNTear>(); if ((Object)(object)component == (Object)null || (Object)(object)component.m_new == (Object)null) { Plugin.Log.LogWarning((object)"Plank deck skipped: wood_floor clone has no WearNTear/New group."); return 0.081f; } PlankTemplate plankTemplate = FindPlankTemplate(component.m_new); if (plankTemplate == null) { Plugin.Log.LogWarning((object)"Plank deck skipped: no plank mesh found in wood_floor New group."); return 0.081f; } float slopeLength = variant.SlopeLength; float num = 2f; float result = 0.081f; bool flag = false; List<GameObject> list = new List<GameObject>(); GameObject[] array = (GameObject[])(object)new GameObject[3] { component.m_new, component.m_worn, component.m_broken }; foreach (GameObject val in array) { if ((Object)(object)val != (Object)null && !list.Contains(val)) { list.Add(val); } } foreach (GameObject item in list) { PlankTemplate plankTemplate2 = FindPlankTemplate(item) ?? plankTemplate; for (int num2 = item.transform.childCount - 1; num2 >= 0; num2--) { Object.DestroyImmediate((Object)(object)((Component)item.transform.GetChild(num2)).gameObject); } Quaternion val2 = (variant.Rotated ? (Quaternion.Euler(0f, 90f, 0f) * plankTemplate2.Rotation) : plankTemplate2.Rotation); int num3; float num4; float sizeX; float sizeZ; if (variant.Rotated) { num3 = Mathf.Max(1, Mathf.RoundToInt(slopeLength / 0.5f)); num4 = slopeLength / (float)num3; sizeX = num; sizeZ = num4; } else { num3 = Mathf.Max(1, Mathf.RoundToInt(num / 0.5f)); num4 = num / (float)num3; sizeX = num4; sizeZ = slopeLength; } Vector3 val3 = FitScale(plankTemplate2, val2, sizeX, sizeZ); Bounds bounds = plankTemplate2.Mesh.bounds; Vector3 val4 = val2 * Vector3.Scale(((Bounds)(ref bounds)).center, val3); for (int j = 0; j < num3; j++) { float num5 = -0.5f * (variant.Rotated ? slopeLength : num) + num4 * ((float)j + 0.5f); Vector3 val5 = (variant.Rotated ? new Vector3(0f, plankTemplate2.Y, num5) : new Vector3(num5, plankTemplate2.Y, 0f)); GameObject val6 = new GameObject($"plank_{j}") { layer = plankTemplate2.Layer }; val6.transform.SetParent(item.transform, false); val6.transform.localPosition = val5 - new Vector3(val4.x, 0f, val4.z); val6.transform.localRotation = val2; val6.transform.localScale = val3; val6.AddComponent<MeshFilter>().sharedMesh = plankTemplate2.Mesh; ((Renderer)val6.AddComponent<MeshRenderer>()).sharedMaterials = plankTemplate2.Materials; } if (!flag) { Bounds bounds2 = plankTemplate2.Mesh.bounds; Vector3 val7 = Vector3.Scale(((Bounds)(ref bounds2)).extents, val3); float num6 = Mathf.Abs((val2 * new Vector3(val7.x, 0f, 0f)).y) + Mathf.Abs((val2 * new Vector3(0f, val7.y, 0f)).y) + Mathf.Abs((val2 * new Vector3(0f, 0f, val7.z)).y); result = plankTemplate2.Y + val4.y + num6; flag = true; } } LODGroup component2 = prefab.GetComponent<LODGroup>(); if ((Object)(object)component2 != (Object)null) { Object.DestroyImmediate((Object)(object)component2); } HashSet<MeshRenderer> hashSet = new HashSet<MeshRenderer>(); MeshRenderer[] array2 = (MeshRenderer[])(object)new MeshRenderer[3] { component.m_snow, component.m_snowWorn, component.m_snowBroken }; foreach (MeshRenderer val8 in array2) { if ((Object)(object)val8 != (Object)null && hashSet.Add(val8)) { Vector3 localScale = ((Component)val8).transform.localScale; localScale.z *= slopeLength / num; ((Component)val8).transform.localScale = localScale; } } return result; } private static Vector3 FitScale(PlankTemplate template, Quaternion rotation, float sizeX, float sizeZ) { //IL_0006: 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_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) Bounds bounds = template.Mesh.bounds; Vector3 size = ((Bounds)(ref bounds)).size; Vector3 scale = template.Scale; for (int i = 0; i < 3; i++) { Vector3 zero = Vector3.zero; ((Vector3)(ref zero))[i] = 1f; Vector3 val = rotation * zero; float num = Mathf.Max(((Vector3)(ref size))[i], 0.0001f); if (Mathf.Abs(val.x) > 0.5f) { ((Vector3)(ref scale))[i] = sizeX / num; } else if (Mathf.Abs(val.z) > 0.5f) { ((Vector3)(ref scale))[i] = sizeZ / num; } } return scale; } private static PlankTemplate FindPlankTemplate(GameObject group) { //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0119: 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) if ((Object)(object)group == (Object)null) { return null; } MeshRenderer[] componentsInChildren = group.GetComponentsInChildren<MeshRenderer>(true); foreach (MeshRenderer val in componentsInChildren) { if ((Object)(object)val == (Object)null || !((Object)val).name.StartsWith("plank", StringComparison.OrdinalIgnoreCase)) { continue; } Vector3 localScale = ((Component)val).transform.localScale; if (!(Mathf.Abs(localScale.x - 0.1f) > 0.03f) && !(Mathf.Abs(localScale.y - 0.5f) > 0.1f) && !(Mathf.Abs(localScale.z - 2f) > 0.2f)) { MeshFilter component = ((Component)val).GetComponent<MeshFilter>(); if (!((Object)(object)component == (Object)null) && !((Object)(object)component.sharedMesh == (Object)null)) { Transform transform = group.transform; return new PlankTemplate { Mesh = component.sharedMesh, Materials = ((Renderer)val).sharedMaterials, Rotation = Quaternion.Inverse(transform.rotation) * ((Component)val).transform.rotation, Scale = localScale, Y = transform.InverseTransformPoint(((Component)val).transform.position).y, Layer = ((Component)val).gameObject.layer }; } } } return null; } 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, float slopeLength, float deckTop) { //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_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: 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, slopeLength); obj.center = new Vector3(0f, deckTop - num, 0f); } private static void BuildSnapPoints(GameObject prefab, Quaternion pitch, float slopeLength, 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_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) float num = 1f; float num2 = slopeLength * 0.5f; int snapCount = 0; AddSnap("$hud_snappoint_top 1", SnapRole.End.High, SnapRole.Lateral.L, new Vector3(num, 0f, 0f - num2)); AddSnap("$hud_snappoint_top 2", SnapRole.End.High, SnapRole.Lateral.R, new Vector3(0f - num, 0f, 0f - num2)); AddSnap("$hud_snappoint_bottom 1", SnapRole.End.Low, SnapRole.Lateral.L, new Vector3(num, 0f, num2)); AddSnap("$hud_snappoint_bottom 2", SnapRole.End.Low, SnapRole.Lateral.R, new Vector3(0f - num, 0f, num2)); Plugin.Log.LogInfo((object)$"Built {snapCount} corner snappoints for {angleDegrees:0.##}° 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> IconsByLabel = new Dictionary<int, Sprite>(); internal static Sprite CreateAngledPieceIcon(GameObject prefab, RampVariant variant, string nameHint) { float angleDegrees = variant.AngleDegrees; bool rotated = variant.Rotated; try { Sprite val = TryLoadPngOverride(variant.Label, rotated, 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 label = variant.Label; if (rotated && IconsByLabel.TryGetValue(label, out var value) && (Object)(object)value != (Object)null) { Plugin.Log.LogInfo((object)($"Icon '{nameHint}': reuse {label}° sprite (rot90 icon matches " + "non-rot; world grain yaw unchanged).")); return value; } Sprite val2 = RenderTopDeckIcon(prefab, angleDegrees, nameHint); if ((Object)(object)val2 != (Object)null && !IconsByLabel.ContainsKey(label)) { IconsByLabel[label] = 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_0090: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0106: 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_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0145: 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.localRotation = Quaternion.Euler(0f - angleDegrees, 0f, 0f); Plugin.Log.LogInfo((object)($"Icon '{nameHint}': capture visual pitch={angleDegrees:0.##}° " + "(icon-only; world prefab untouched).")); Quaternion rotation = RenderManager.IsometricRotation * Quaternion.Euler(angleDegrees * 0.5f, 0f, 0f) * Quaternion.Euler(0f, 180f, 0f); RenderRequest val3 = new RenderRequest(val) { Rotation = rotation, Width = 512, Height = 512, DistanceMultiplier = 1f, 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:0.##}°, " + $"cam=Iso*Euler({angleDegrees * 0.5f:0.#},0,0)*Y180, " + $"dist×={1f}, {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(int label, 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(label, 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(int label, bool rotateTexture90) { string text = "wood_floor_" + label; 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_0040: 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_005a: Unknown result type (might be due to invalid IL or missing references) GameObject clone = Object.Instantiate<GameObject>(prefab); ((Object)clone).name = ((Object)prefab).name + "_IconOnly"; ((Object)clone).hideFlags = (HideFlags)61; clone.transform.SetPositionAndRotation(Vector3.zero, Quaternion.identity); clone.transform.localScale = Vector3.one; List<GameObject> wearOverlays = new List<GameObject>(); WearNTear component = clone.GetComponent<WearNTear>(); GameObject healthy; if ((Object)(object)component != (Object)null) { healthy = component.m_new; AddOverlay(((Object)(object)component.m_snow != (Object)null) ? ((Component)component.m_snow).gameObject : null); AddOverlay(((Object)(object)component.m_snowWorn != (Object)null) ? ((Component)component.m_snowWorn).gameObject : null); AddOverlay(((Object)(object)component.m_snowBroken != (Object)null) ? ((Component)component.m_snowBroken).gameObject : null); AddOverlay(component.m_worn); AddOverlay(component.m_broken); AddOverlay(component.m_wet); } foreach (GameObject item in wearOverlays) { if ((Object)(object)item != (Object)null) { Object.DestroyImmediate((Object)(object)item); } } Component[] componentsInChildren = clone.GetComponentsInChildren<Component>(true); foreach (Component val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && !(val is Transform) && !(val is MeshFilter) && !(val is MeshRenderer) && !(val is SkinnedMeshRenderer)) { try { Object.DestroyImmediate((Object)(object)val); } catch { } } } Transform val2 = clone.transform.Find("FloorVisual"); if ((Object)(object)val2 == (Object)null) { Object.DestroyImmediate((Object)(object)clone); return null; } List<GameObject> list = new List<GameObject>(); for (int j = 0; j < clone.transform.childCount; j++) { Transform child = clone.transform.GetChild(j); if ((Object)(object)child != (Object)null && (Object)(object)child != (Object)(object)val2) { list.Add(((Component)child).gameObject); } } Transform[] componentsInChildren2 = ((Component)val2).GetComponentsInChildren<Transform>(true); foreach (Transform val3 in componentsInChildren2) { if (!((Object)(object)val3 == (Object)null) && !((Object)(object)val3 == (Object)(object)val2)) { string text = ((Object)val3).name ?? string.Empty; if (text.IndexOf("worn", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("broken", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("snow", 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)val3).gameObject); } } } foreach (GameObject item2 in list) { if ((Object)(object)item2 != (Object)null) { Object.DestroyImmediate((Object)(object)item2); } } MeshRenderer[] componentsInChildren3 = ((Component)val2).GetComponentsInChildren<MeshRenderer>(true); if (componentsInChildren3 == null || componentsInChildren3.Length == 0) { Object.DestroyImmediate((Object)(object)clone); return null; } MeshRenderer[] array = componentsInChildren3; foreach (MeshRenderer val4 in array) { if ((Object)(object)val4 != (Object)null) { ((Renderer)val4).enabled = true; ((Component)val4).gameObject.SetActive(true); } } clone.SetActive(true); return clone; void AddOverlay(GameObject go) { if (!((Object)(object)go == (Object)null) && !((Object)(object)go == (Object)(object)clone) && !((Object)(object)go == (Object)(object)healthy) && (!((Object)(object)healthy != (Object)null) || !healthy.transform.IsChildOf(go.transform)) && !(((Object)go).name == "FloorVisual")) { wearOverlays.Add(go); } } } 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 static readonly RampVariant[] Variants = new RampVariant[6] { Make(26, 1f, rotated: false, "Wood Ramp 26°", "A wood ramp that matches vanilla 26° beams and thatch roofs (2 m across, 1 m rise)."), Make(45, 2f, rotated: false, "Wood Ramp 45°", "A wood ramp that matches vanilla 45° beams and thatch roofs (2 m across, 2 m rise)."), Make(67, 4f, rotated: false, "Wood Ramp 67°", "A wood ramp that matches vanilla 67° beams and thatch roofs (2 m across, 4 m rise)."), Make(26, 1f, rotated: true, "Wood Ramp 26° (Rotated)", "Same slope as Wood Ramp 26°, with plank grain rotated 90°."), Make(45, 2f, rotated: true, "Wood Ramp 45° (Rotated)", "Same slope as Wood Ramp 45°, with plank grain rotated 90°."), Make(67, 4f, rotated: true, "Wood Ramp 67° (Rotated)", "Same slope as Wood Ramp 67°, with plank grain rotated 90°.") }; private static readonly HashSet<string> PieceNames = BuildPieceNames(); private static bool _registered; private static RampVariant Make(int label, float rise, bool rotated, string displayName, string description) { string arg = (rotated ? "_rot90" : string.Empty); return new RampVariant { Label = label, Rise = rise, Rotated = rotated, PieceName = $"piece_wood_floor_{label}{arg}", TokenName = $"$woodramps_ramp{label}{arg}_name", TokenDescription = $"$woodramps_ramp{label}{arg}_description", DisplayName = displayName, Description = description }; } private static HashSet<string> BuildPieceNames() { HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal); RampVariant[] variants = Variants; foreach (RampVariant rampVariant in variants) { hashSet.Add(rampVariant.PieceName); } return hashSet; } internal static void Register() { CustomLocalization localization = LocalizationManager.Instance.GetLocalization(); RampVariant[] variants = Variants; foreach (RampVariant rampVariant in variants) { string text = "English"; localization.AddTranslation(ref text, ref rampVariant.TokenName, rampVariant.DisplayName); text = "English"; localization.AddTranslation(ref text, ref rampVariant.TokenDescription, rampVariant.Description); } PrefabManager.OnVanillaPrefabsAvailable += OnVanillaPrefabsAvailable; } internal static void Unregister() { PrefabManager.OnVanillaPrefabsAvailable -= OnVanillaPrefabsAvailable; } private static void OnVanillaPrefabsAvailable() { if (_registered) { return; } try { bool flag = true; RampVariant[] variants = Variants; foreach (RampVariant variant in variants) { flag &= RegisterFloor(variant); } if (!flag) { Plugin.Log.LogError((object)"One or more wood ramp pieces failed to register."); return; } _registered = true; PrefabManager.OnVanillaPrefabsAvailable -= OnVanillaPrefabsAvailable; Plugin.Log.LogInfo((object)$"Registered {Variants.Length} wood ramp pieces (26°, 45°, 67° + rotated)."); } catch (Exception arg) { Plugin.Log.LogError((object)$"Failed to register wood ramps: {arg}"); } } private static bool RegisterFloor(RampVariant variant) { //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Expected O, but got Unknown //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Expected O, but got Unknown //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Expected O, but got Unknown string pieceName = variant.PieceName; GameObject val = FloorPrefabBuilder.CreateAngledFloor(variant); 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, variant, pieceName + "_icon"); } catch (Exception ex) { Plugin.Log.LogWarning((object)("Icon resolve failed for '" + pieceName + "': " + ex.Message)); val2 = null; } PieceConfig val3 = new PieceConfig { Name = variant.TokenName, Description = variant.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 arg = (variant.Rotated ? ", plank yaw 90°" : string.Empty); Plugin.Log.LogInfo((object)($"Registered build piece '{pieceName}' at {variant.AngleDegrees:0.##}° " + $"(rise {variant.Rise} m{arg}, hash {stableHashCode}).")); return true; } internal static bool IsAngledWoodFloor(GameObject go) { if ((Object)(object)go == (Object)null) { return false; } string item = ((Object)go).name.Replace("(Clone)", string.Empty).Trim(); return PieceNames.Contains(item); } 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.1")] [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.1"; 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.1 loaded."); } private void OnDestroy() { PieceRegistration.Unregister(); Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } _harmony = null; } } internal sealed class RampVariant { internal const float Run = 2f; internal const float PlankWidth = 0.5f; internal int Label; internal float Rise; internal bool Rotated; internal string PieceName; internal string TokenName; internal string TokenDescription; internal string DisplayName; internal string Description; internal float AngleDegrees => Mathf.Atan2(Rise, 2f) * 57.29578f; internal float SlopeLength => Mathf.Sqrt(4f + Rise * Rise); } 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) { } } }