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 SymmetricalBuildingPieces v1.0.0
plugins/SymmetricalBuildingPieces.dll
Decompiled 6 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.Rendering; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyVersion("0.0.0.0")] [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 SymmetricalBuildingPieces { internal static class MeshSymmetrizer { private sealed class Vtx { public Vector3 P; public Vector3 N; public Vector4 T; public Color C; public readonly Vector4[] Uv = (Vector4[])(object)new Vector4[4]; public float D; } private const float InsideEps = 1E-05f; private const float OnPlaneEps = 0.0001f; private const int UvChannels = 4; public static void Build(Mesh src, Mesh dst, Matrix4x4 meshToRoot, Vector3 planePoint, Vector3 keepNormal) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: 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_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_017a: 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_0184: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: 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_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_01b1: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: Unknown result type (might be due to invalid IL or missing references) //IL_01ce: 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_01dc: Unknown result type (might be due to invalid IL or missing references) //IL_01e1: Unknown result type (might be due to invalid IL or missing references) //IL_01e5: Unknown result type (might be due to invalid IL or missing references) //IL_01ec: Unknown result type (might be due to invalid IL or missing references) //IL_01f3: Unknown result type (might be due to invalid IL or missing references) //IL_01fe: Unknown result type (might be due to invalid IL or missing references) //IL_0208: Unknown result type (might be due to invalid IL or missing references) //IL_020d: Unknown result type (might be due to invalid IL or missing references) //IL_0225: Unknown result type (might be due to invalid IL or missing references) //IL_022a: Unknown result type (might be due to invalid IL or missing references) //IL_034e: Unknown result type (might be due to invalid IL or missing references) //IL_0354: Invalid comparison between Unknown and I4 //IL_0272: 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_027d: Unknown result type (might be due to invalid IL or missing references) //IL_0283: Unknown result type (might be due to invalid IL or missing references) //IL_0253: Unknown result type (might be due to invalid IL or missing references) //IL_0258: Unknown result type (might be due to invalid IL or missing references) ((Vector3)(ref keepNormal)).Normalize(); Matrix4x4 rootToMesh = ((Matrix4x4)(ref meshToRoot)).inverse; Matrix4x4 transpose = ((Matrix4x4)(ref rootToMesh)).transpose; Matrix4x4 normalToMesh = ((Matrix4x4)(ref meshToRoot)).transpose; List<Vector3> list = new List<Vector3>(); src.GetVertices(list); List<Vector3> list2 = new List<Vector3>(); src.GetNormals(list2); List<Vector4> list3 = new List<Vector4>(); src.GetTangents(list3); List<Color> list4 = new List<Color>(); src.GetColors(list4); int count = list.Count; bool hasN = list2.Count == count; bool hasT = list3.Count == count; bool hasC = list4.Count == count; List<Vector4>[] array = new List<Vector4>[4]; bool[] hasUv = new bool[4]; int[] array2 = new int[4]; for (int i = 0; i < 4; i++) { array[i] = new List<Vector4>(); VertexAttribute val = (VertexAttribute)(4 + i); hasUv[i] = src.HasVertexAttribute(val); if (hasUv[i]) { src.GetUVs(i, array[i]); hasUv[i] = array[i].Count == count; array2[i] = src.GetVertexAttributeDimension(val); } } Vtx[] array3 = new Vtx[count]; for (int j = 0; j < count; j++) { Vtx vtx = new Vtx { P = ((Matrix4x4)(ref meshToRoot)).MultiplyPoint3x4(list[j]) }; Vector3 val2; if (hasN) { val2 = ((Matrix4x4)(ref transpose)).MultiplyVector(list2[j]); vtx.N = ((Vector3)(ref val2)).normalized; } if (hasT) { val2 = ((Matrix4x4)(ref meshToRoot)).MultiplyVector(Vector4.op_Implicit(list3[j])); Vector3 normalized = ((Vector3)(ref val2)).normalized; vtx.T = new Vector4(normalized.x, normalized.y, normalized.z, list3[j].w); } if (hasC) { vtx.C = list4[j]; } for (int k = 0; k < 4; k++) { if (hasUv[k]) { vtx.Uv[k] = array[k][j]; } } vtx.D = Vector3.Dot(vtx.P - planePoint, keepNormal); array3[j] = vtx; } List<Vector3> oPos = new List<Vector3>(); List<Vector3> oNrm = new List<Vector3>(); List<Vector4> oTan = new List<Vector4>(); List<Color> oCol = new List<Color>(); List<Vector4>[] oUv = new List<Vector4>[4]; for (int l = 0; l < 4; l++) { oUv[l] = new List<Vector4>(); } int subMeshCount = src.subMeshCount; List<int>[] array4 = new List<int>[subMeshCount]; List<int> list5 = new List<int>(); List<Vtx> list6 = new List<Vtx>(4); for (int m = 0; m < subMeshCount; m++) { List<int> list7 = (array4[m] = new List<int>()); if ((int)src.GetTopology(m) > 0) { continue; } list5.Clear(); src.GetTriangles(list5, m); for (int n = 0; n + 2 < list5.Count; n += 3) { Vtx vtx2 = array3[list5[n]]; Vtx vtx3 = array3[list5[n + 1]]; Vtx vtx4 = array3[list5[n + 2]]; if (!(Mathf.Abs(vtx2.D) < 0.0001f) || !(Mathf.Abs(vtx3.D) < 0.0001f) || !(Mathf.Abs(vtx4.D) < 0.0001f)) { ClipToKeepSide(vtx2, vtx3, vtx4, list6); for (int num = 1; num + 1 < list6.Count; num++) { Vtx v = list6[0]; Vtx v2 = list6[num]; Vtx v3 = list6[num + 1]; list7.Add(Emit(v, mirror: false)); list7.Add(Emit(v2, mirror: false)); list7.Add(Emit(v3, mirror: false)); list7.Add(Emit(v, mirror: true)); list7.Add(Emit(v3, mirror: true)); list7.Add(Emit(v2, mirror: true)); } } } } dst.Clear(); dst.indexFormat = (IndexFormat)(oPos.Count > 65000); dst.SetVertices(oPos); if (hasN) { dst.SetNormals(oNrm); } if (hasT) { dst.SetTangents(oTan); } if (hasC) { dst.SetColors(oCol); } for (int num2 = 0; num2 < 4; num2++) { if (!hasUv[num2]) { continue; } if (array2[num2] <= 2) { dst.SetUVs(num2, oUv[num2].ConvertAll((Converter<Vector4, Vector2>)((Vector4 u) => new Vector2(u.x, u.y)))); } else if (array2[num2] == 3) { dst.SetUVs(num2, oUv[num2].ConvertAll((Converter<Vector4, Vector3>)((Vector4 u) => new Vector3(u.x, u.y, u.z)))); } else { dst.SetUVs(num2, oUv[num2]); } } dst.subMeshCount = subMeshCount; for (int num3 = 0; num3 < subMeshCount; num3++) { dst.SetTriangles(array4[num3], num3, false); } if (!hasN) { dst.RecalculateNormals(); } if (!hasT && hasN) { dst.RecalculateTangents(); } dst.RecalculateBounds(); int Emit(Vtx vtx5, bool mirror) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0009: 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_00d9: 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_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005b: 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_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_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0080: 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_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0095: 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_009f: 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_00a5: 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_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: 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_0107: 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_0126: 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_012f: 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_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Unknown result type (might be due to invalid IL or missing references) Vector3 val3 = vtx5.P; Vector3 val4 = vtx5.N; Vector3 val5 = default(Vector3); ((Vector3)(ref val5))..ctor(vtx5.T.x, vtx5.T.y, vtx5.T.z); float num4 = vtx5.T.w; if (mirror) { float num5 = Vector3.Dot(val3 - planePoint, keepNormal); val3 -= 2f * num5 * keepNormal; val4 -= 2f * Vector3.Dot(val4, keepNormal) * keepNormal; val5 -= 2f * Vector3.Dot(val5, keepNormal) * keepNormal; num4 = 0f - num4; } oPos.Add(((Matrix4x4)(ref rootToMesh)).MultiplyPoint3x4(val3)); Vector3 val6; if (hasN) { List<Vector3> list8 = oNrm; val6 = ((Matrix4x4)(ref normalToMesh)).MultiplyVector(val4); list8.Add(((Vector3)(ref val6)).normalized); } if (hasT) { val6 = ((Matrix4x4)(ref rootToMesh)).MultiplyVector(val5); Vector3 normalized2 = ((Vector3)(ref val6)).normalized; oTan.Add(new Vector4(normalized2.x, normalized2.y, normalized2.z, num4)); } if (hasC) { oCol.Add(vtx5.C); } for (int num6 = 0; num6 < 4; num6++) { if (hasUv[num6]) { oUv[num6].Add(vtx5.Uv[num6]); } } return oPos.Count - 1; } } private static void ClipToKeepSide(Vtx a, Vtx b, Vtx c, List<Vtx> result) { result.Clear(); Vtx[] array = new Vtx[3] { a, b, c }; for (int i = 0; i < 3; i++) { Vtx vtx = array[i]; Vtx vtx2 = array[(i + 1) % 3]; bool flag = vtx.D >= -1E-05f; bool flag2 = vtx2.D >= -1E-05f; if (flag) { result.Add(vtx); } if (flag != flag2) { result.Add(Lerp(vtx, vtx2, vtx.D / (vtx.D - vtx2.D))); } } if (result.Count < 3) { result.Clear(); } } private static Vtx Lerp(Vtx a, Vtx b, float t) { //IL_0008: 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_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0034: 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_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0046: 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_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0083: 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_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00be: 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) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00db: 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_00f7: 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_0109: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) Vtx obj = new Vtx { P = Vector3.Lerp(a.P, b.P, t) }; Vector3 val = Vector3.Lerp(a.N, b.N, t); obj.N = ((Vector3)(ref val)).normalized; obj.C = Color.Lerp(a.C, b.C, t); obj.D = 0f; Vtx vtx = obj; val = Vector3.Lerp(new Vector3(a.T.x, a.T.y, a.T.z), new Vector3(b.T.x, b.T.y, b.T.z), t); Vector3 normalized = ((Vector3)(ref val)).normalized; vtx.T = new Vector4(normalized.x, normalized.y, normalized.z, a.T.w); for (int i = 0; i < 4; i++) { vtx.Uv[i] = Vector4.Lerp(a.Uv[i], b.Uv[i], t); } return vtx; } } internal static class PieceRegistry { private sealed class MeshPair { public MeshFilter Filter; public Mesh Source; public Mesh Result; } private sealed class Entry { public string Source; public GameObject Clone; public readonly List<MeshPair> Meshes = new List<MeshPair>(); } public const string ClonePrefix = "SBP_"; private static readonly Dictionary<string, Entry> Entries = new Dictionary<string, Entry>(); private static readonly HashSet<string> Missing = new HashSet<string>(); private static GameObject _holder; private static readonly FieldRef<ZNetScene, Dictionary<int, GameObject>> NamedPrefabs = AccessTools.FieldRefAccess<ZNetScene, Dictionary<int, GameObject>>("m_namedPrefabs"); private static MethodInfo _loadImage; private static Dictionary<string, char> ParsePieceList() { Dictionary<string, char> dictionary = new Dictionary<string, char>(StringComparer.Ordinal); string[] array = Plugin.PieceList.Value.Split(new char[3] { ',', ';', '\n' }, StringSplitOptions.RemoveEmptyEntries); foreach (string text in array) { string text2 = text.Trim(); if (text2.Length != 0) { string[] array2 = text2.Split(new char[1] { ':' }); string key = array2[0].Trim(); int num; switch ((array2.Length > 1) ? array2[1].Trim().ToLowerInvariant() : "auto") { default: num = 97; break; case "flip": num = 102; break; case "-": case "back": num = 45; break; case "+": case "front": num = 43; break; } char value = (char)num; dictionary[key] = value; } } return dictionary; } public static void TrySetup() { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown if ((Object)(object)ZNetScene.instance == (Object)null || (Object)(object)ObjectDB.instance == (Object)null) { return; } if ((Object)(object)_holder == (Object)null) { _holder = new GameObject("SBP_PrefabHolder"); _holder.SetActive(false); Object.DontDestroyOnLoad((Object)(object)_holder); } foreach (KeyValuePair<string, char> item in ParsePieceList()) { if (!Entries.ContainsKey(item.Key) && !Missing.Contains(item.Key)) { CreateClone(item.Key, item.Value); } } RegisterWithZNetScene(); AddToHammer(); } private static void CreateClone(string sourceName, char side) { //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Expected O, but got Unknown GameObject prefab = ZNetScene.instance.GetPrefab(sourceName); if ((Object)(object)prefab == (Object)null || (Object)(object)prefab.GetComponent<Piece>() == (Object)null) { Missing.Add(sourceName); Plugin.Log.LogWarning((object)("'" + sourceName + "' is not a known piece prefab. Run 'sbp_dump' in the F5 console to list prefab names.")); return; } GameObject val = Object.Instantiate<GameObject>(prefab, _holder.transform, false); ((Object)val).name = "SBP_" + sourceName; Piece component = val.GetComponent<Piece>(); component.m_name += Plugin.NameSuffix.Value; Sprite val2 = LoadIconOverride(sourceName); if ((Object)(object)val2 != (Object)null) { component.m_icon = val2; } Entry entry = new Entry { Source = sourceName, Clone = val }; MeshFilter[] componentsInChildren = val.GetComponentsInChildren<MeshFilter>(true); foreach (MeshFilter val3 in componentsInChildren) { Mesh sharedMesh = val3.sharedMesh; if (!((Object)(object)sharedMesh == (Object)null)) { if (!sharedMesh.isReadable) { Plugin.Log.LogError((object)(sourceName + ": mesh '" + ((Object)sharedMesh).name + "' on '" + GetPath(((Component)val3).transform, val.transform) + "' is not readable — left unchanged.")); } else { Mesh val4 = new Mesh { name = ((Object)sharedMesh).name + "_sym" }; entry.Meshes.Add(new MeshPair { Filter = val3, Source = sharedMesh, Result = val4 }); val3.sharedMesh = val4; } } } Entries[sourceName] = entry; Build(entry, side); Plugin.Log.LogInfo((object)$"Created {((Object)val).name} ({entry.Meshes.Count} meshes symmetrized)."); } private static void Build(Entry entry, char side) { //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: 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) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: 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_00f9: 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) if (entry.Meshes.Count == 0) { return; } Transform transform = entry.Clone.transform; Analyze(transform, entry.Meshes.Select((MeshPair m) => (Filter: m.Filter, Source: m.Source)), out var axis, out var planePoint, out var posExtent, out var negExtent); char c = ((Mathf.Abs(posExtent - negExtent) < 0.005f) ? '+' : ((posExtent < negExtent) ? '+' : '-')); char c2 = side switch { 'f' => (c == '+') ? '-' : '+', 'a' => c, _ => side, }; Vector3 keepNormal = ((c2 == '+') ? axis : (-axis)); foreach (MeshPair mesh in entry.Meshes) { Matrix4x4 meshToRoot = transform.worldToLocalMatrix * ((Component)mesh.Filter).transform.localToWorldMatrix; MeshSymmetrizer.Build(mesh.Source, mesh.Result, meshToRoot, planePoint, keepNormal); } Plugin.Log.LogInfo((object)$"{((Object)entry.Clone).name}: thin axis {AxisName(axis)}, extents +{posExtent:0.###} / -{negExtent:0.###}, keeping '{c2}' side (config: '{side}')."); } private static void Analyze(Transform root, IEnumerable<(MeshFilter filter, Mesh mesh)> meshes, out Vector3 axis, out Vector3 planePoint, out float posExtent, out float negExtent) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: 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_004a: 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_0073: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: 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_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: 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_0103: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0114: 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_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0124: 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_0095: 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_009c: 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_00a3: 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_00a6: 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_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) Vector3 val = Vector3.positiveInfinity; Vector3 val2 = Vector3.negativeInfinity; List<Vector3> list = new List<Vector3>(); foreach (var mesh in meshes) { MeshFilter item = mesh.filter; Mesh item2 = mesh.mesh; Matrix4x4 val3 = root.worldToLocalMatrix * ((Component)item).transform.localToWorldMatrix; list.Clear(); if (item2.isReadable) { item2.GetVertices(list); } else { list.AddRange(BoundsCorners(item2.bounds)); } foreach (Vector3 item3 in list) { Vector3 val4 = ((Matrix4x4)(ref val3)).MultiplyPoint3x4(item3); val = Vector3.Min(val, val4); val2 = Vector3.Max(val2, val4); } } Vector3 val5 = val2 - val; axis = ((val5.x < val5.z) ? Vector3.right : Vector3.forward); float num = Vector3.Dot(val, axis); float num2 = Vector3.Dot(val2, axis); float num3 = ((Plugin.Plane.Value == PlaneMode.BoundsCenter) ? ((num + num2) * 0.5f) : 0f); num3 += Plugin.PlaneOffset.Value; planePoint = axis * num3; posExtent = num2 - num3; negExtent = num3 - num; } public static void RebuildAll() { Dictionary<string, char> dictionary = ParsePieceList(); foreach (Entry value2 in Entries.Values) { Build(value2, dictionary.TryGetValue(value2.Source, out var value) ? value : 'a'); } if (dictionary.Keys.Any((string k) => !Entries.ContainsKey(k) && !Missing.Contains(k))) { Plugin.Log.LogInfo((object)"New pieces in the list will be added the next time a world loads."); } } private static void RegisterWithZNetScene() { ZNetScene instance = ZNetScene.instance; Dictionary<int, GameObject> dictionary = NamedPrefabs.Invoke(instance); foreach (Entry value in Entries.Values) { if (!instance.m_prefabs.Contains(value.Clone)) { instance.m_prefabs.Add(value.Clone); } dictionary[StringExtensionMethods.GetStableHashCode(((Object)value.Clone).name)] = value.Clone; } } private static void AddToHammer() { GameObject itemPrefab = ObjectDB.instance.GetItemPrefab("Hammer"); PieceTable val = ((!Object.op_Implicit((Object)(object)itemPrefab)) ? null : itemPrefab.GetComponent<ItemDrop>()?.m_itemData.m_shared.m_buildPieces); if ((Object)(object)val == (Object)null) { Plugin.Log.LogWarning((object)"Hammer piece table not found."); return; } List<GameObject> pieces = val.m_pieces; foreach (Entry e in Entries.Values) { if (!pieces.Contains(e.Clone)) { int num = pieces.FindIndex((GameObject p) => (Object)(object)p != (Object)null && ((Object)p).name == e.Source); if (num >= 0) { pieces.Insert(num + 1, e.Clone); } else { pieces.Add(e.Clone); } } } } public static int Dump(string filter) { //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_02dd: Unknown result type (might be due to invalid IL or missing references) GameObject val = (Object.op_Implicit((Object)(object)ObjectDB.instance) ? ObjectDB.instance.GetItemPrefab("Hammer") : null); PieceTable val2 = ((!Object.op_Implicit((Object)(object)val)) ? null : val.GetComponent<ItemDrop>()?.m_itemData.m_shared.m_buildPieces); if ((Object)(object)val2 == (Object)null) { return 0; } StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine("===== SBP dump (filter: '" + filter + "') ====="); int num = 0; foreach (GameObject piece in val2.m_pieces) { if ((Object)(object)piece == (Object)null || ((Object)piece).name.StartsWith("SBP_")) { continue; } Piece component = piece.GetComponent<Piece>(); string text = ((Object.op_Implicit((Object)(object)component) && Localization.instance != null) ? Localization.instance.Localize(component.m_name) : ""); if (((Object)piece).name.IndexOf(filter, StringComparison.OrdinalIgnoreCase) < 0 && text.IndexOf(filter, StringComparison.OrdinalIgnoreCase) < 0) { continue; } num++; stringBuilder.AppendLine($"{((Object)piece).name} | \"{text}\" | category {component?.m_category}"); List<MeshFilter> list = (from f in piece.GetComponentsInChildren<MeshFilter>(true) where (Object)(object)f.sharedMesh != (Object)null select f).ToList(); foreach (MeshFilter item in list) { Mesh sharedMesh = item.sharedMesh; MeshRenderer component2 = ((Component)item).GetComponent<MeshRenderer>(); string text2 = (Object.op_Implicit((Object)(object)component2) ? string.Join(", ", ((Renderer)component2).sharedMaterials.Select((Material m) => Object.op_Implicit((Object)(object)m) ? ((Object)m).name : "null")) : "-"); stringBuilder.AppendLine($" {GetPath(((Component)item).transform, piece.transform)}: mesh '{((Object)sharedMesh).name}' readable={sharedMesh.isReadable} verts={sharedMesh.vertexCount} submeshes={sharedMesh.subMeshCount} mats=[{text2}]"); } if (list.Count > 0) { Analyze(piece.transform, list.Select((MeshFilter f) => (f: f, sharedMesh: f.sharedMesh)), out var axis, out var _, out var posExtent, out var negExtent); stringBuilder.AppendLine($" thin axis {AxisName(axis)}, extents from plane: +{posExtent:0.###} / -{negExtent:0.###}"); } } stringBuilder.AppendLine($"===== {num} pieces ====="); Plugin.Log.LogInfo((object)stringBuilder.ToString()); return num; } private static Sprite LoadIconOverride(string sourceName) { //IL_0081: 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) //IL_009a: Expected O, but got Unknown //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) string path = Path.GetDirectoryName(Plugin.PluginPath) ?? ""; string[] source = new string[2] { Path.Combine(path, "icons", sourceName + ".png"), Path.Combine(path, sourceName + ".png") }; string text = source.FirstOrDefault(File.Exists); if (text == null) { return null; } try { Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false) { name = "SBP_icon_" + sourceName }; if (!LoadImage(val, File.ReadAllBytes(text))) { Plugin.Log.LogWarning((object)("Could not decode icon '" + text + "'.")); return null; } ((Texture)val).wrapMode = (TextureWrapMode)1; Plugin.Log.LogInfo((object)("Using custom icon for " + sourceName + ": " + text)); return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f); } catch (Exception ex) { Plugin.Log.LogWarning((object)("Failed to load icon '" + text + "': " + ex.Message)); return null; } } private static bool LoadImage(Texture2D tex, byte[] data) { if (_loadImage == null) { _loadImage = Type.GetType("UnityEngine.ImageConversion, UnityEngine.ImageConversionModule")?.GetMethod("LoadImage", new Type[2] { typeof(Texture2D), typeof(byte[]) }); if (_loadImage == null) { Plugin.Log.LogWarning((object)"UnityEngine.ImageConversion.LoadImage not found; custom icons disabled."); return false; } } return (bool)_loadImage.Invoke(null, new object[2] { tex, data }); } private static string AxisName(Vector3 axis) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) return (axis == Vector3.right) ? "X" : "Z"; } private static IEnumerable<Vector3> BoundsCorners(Bounds b) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < 8; i++) { yield return new Vector3(((i & 1) == 0) ? ((Bounds)(ref b)).min.x : ((Bounds)(ref b)).max.x, ((i & 2) == 0) ? ((Bounds)(ref b)).min.y : ((Bounds)(ref b)).max.y, ((i & 4) == 0) ? ((Bounds)(ref b)).min.z : ((Bounds)(ref b)).max.z); } } private static string GetPath(Transform t, Transform root) { List<string> list = new List<string>(); while ((Object)(object)t != (Object)null && (Object)(object)t != (Object)(object)root) { list.Add(((Object)t).name); t = t.parent; } list.Reverse(); return (list.Count == 0) ? "(root)" : string.Join("/", list); } } public enum PlaneMode { Pivot, BoundsCenter } [BepInPlugin("bhimajenkins.symmetricalbuildingpieces", "Symmetrical Building Pieces", "1.0.0")] public class Plugin : BaseUnityPlugin { public const string Guid = "bhimajenkins.symmetricalbuildingpieces"; public const string Name = "Symmetrical Building Pieces"; public const string Version = "1.0.0"; internal static ManualLogSource Log; internal static string PluginPath; internal static ConfigEntry<string> PieceList; internal static ConfigEntry<string> NameSuffix; internal static ConfigEntry<PlaneMode> Plane; internal static ConfigEntry<float> PlaneOffset; private const string DefaultPieces = "woodwall, wood_wall_half, wood_wall_quarter, scale_wall_2x2, scale_halfwall_1x2, scale_quarterwall_1x1, scale_wall_roof_26:flip, scale_wall_roof_45:flip, scale_wall_roof_67, scale_wall_roof_26_upsidedown_flipped, scale_wall_roof_45_upsidedown_flipped, scale_wall_roof_67_upsidedown_flipped, ashwood_quarterwall_1x1:flip, ashwood_halfwall_1x2, ashwood_wall_2x2, stave_wall_2x2"; private void Awake() { //IL_012b: Unknown result type (might be due to invalid IL or missing references) Log = ((BaseUnityPlugin)this).Logger; PluginPath = ((BaseUnityPlugin)this).Info.Location; PieceList = ((BaseUnityPlugin)this).Config.Bind<string>("General", "Pieces", "woodwall, wood_wall_half, wood_wall_quarter, scale_wall_2x2, scale_halfwall_1x2, scale_quarterwall_1x1, scale_wall_roof_26:flip, scale_wall_roof_45:flip, scale_wall_roof_67, scale_wall_roof_26_upsidedown_flipped, scale_wall_roof_45_upsidedown_flipped, scale_wall_roof_67_upsidedown_flipped, ashwood_quarterwall_1x1:flip, ashwood_halfwall_1x2, ashwood_wall_2x2, stave_wall_2x2", "Comma-separated vanilla prefab names to make symmetrical copies of.\nAdd ':+' or ':-' to force which face is kept, or ':flip' for the opposite of auto (default 'auto' keeps the flatter face).\nExample: woodwall:+, wood_wall_half:-\nChanging a side rebuilds placed pieces live; newly added names apply on next world load."); NameSuffix = ((BaseUnityPlugin)this).Config.Bind<string>("General", "NameSuffix", " (Symmetrical)", "Text added after the vanilla name in the build menu. Takes effect on restart."); Plane = ((BaseUnityPlugin)this).Config.Bind<PlaneMode>("Advanced", "MirrorPlane", PlaneMode.Pivot, "Where the mirror plane sits. Pivot = piece origin. BoundsCenter = middle of the thickness."); PlaneOffset = ((BaseUnityPlugin)this).Config.Bind<float>("Advanced", "MirrorPlaneOffset", 0f, "Extra offset (metres) of the mirror plane along the wall's thickness axis."); PieceList.SettingChanged += delegate { PieceRegistry.RebuildAll(); }; Plane.SettingChanged += delegate { PieceRegistry.RebuildAll(); }; PlaneOffset.SettingChanged += delegate { PieceRegistry.RebuildAll(); }; new Harmony("bhimajenkins.symmetricalbuildingpieces").PatchAll(); } } [HarmonyPatch(typeof(ZNetScene), "Awake")] internal static class ZNetSceneAwakePatch { [HarmonyPriority(0)] private static void Postfix() { PieceRegistry.TrySetup(); } } [HarmonyPatch(typeof(ObjectDB), "Awake")] internal static class ObjectDBAwakePatch { [HarmonyPriority(0)] private static void Postfix() { PieceRegistry.TrySetup(); } } [HarmonyPatch(typeof(Terminal), "InitTerminal")] internal static class TerminalPatch { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static ConsoleEvent <>9__0_0; public static ConsoleEvent <>9__0_1; internal void <Postfix>b__0_0(ConsoleEventArgs args) { string filter = ((args.Length > 1) ? args[1] : "wall"); int num = PieceRegistry.Dump(filter); Terminal context = args.Context; if (context != null) { context.AddString($"SBP: {num} pieces written to BepInEx/LogOutput.log"); } } internal void <Postfix>b__0_1(ConsoleEventArgs args) { ((ConfigEntryBase)Plugin.PieceList).ConfigFile.Reload(); PieceRegistry.RebuildAll(); Terminal context = args.Context; if (context != null) { context.AddString("SBP: rebuilt"); } } } private static void Postfix() { //IL_0034: 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_002a: Expected O, but got Unknown //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Expected O, but got Unknown object obj = <>c.<>9__0_0; if (obj == null) { ConsoleEvent val = delegate(ConsoleEventArgs args) { string filter = ((args.Length > 1) ? args[1] : "wall"); int num = PieceRegistry.Dump(filter); Terminal context = args.Context; if (context != null) { context.AddString($"SBP: {num} pieces written to BepInEx/LogOutput.log"); } }; <>c.<>9__0_0 = val; obj = (object)val; } new ConsoleCommand("sbp_dump", "[filter] - log Hammer pieces whose prefab or display name contains filter (default 'wall'), with mesh info", (ConsoleEvent)obj, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); object obj2 = <>c.<>9__0_1; if (obj2 == null) { ConsoleEvent val2 = delegate(ConsoleEventArgs args) { ((ConfigEntryBase)Plugin.PieceList).ConfigFile.Reload(); PieceRegistry.RebuildAll(); Terminal context = args.Context; if (context != null) { context.AddString("SBP: rebuilt"); } }; <>c.<>9__0_1 = val2; obj2 = (object)val2; } new ConsoleCommand("sbp_rebuild", "- re-read the SBP config and rebuild all symmetrical meshes", (ConsoleEvent)obj2, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); } } }