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 ValFrames v0.5.0
plugins/ValFrames.dll
Decompiled 2 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.IO.Compression; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Logging; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using Jotunn.Utils; 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: AssemblyCompany("DezzyCode")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("DezzyCode")] [assembly: AssemblyDescription("Pictures in frames to hang on your walls.")] [assembly: AssemblyFileVersion("0.5.0.0")] [assembly: AssemblyInformationalVersion("0.5.0+b69c79bebae53fe39b25402c20d0dd073c85ea38")] [assembly: AssemblyProduct("ValFrames")] [assembly: AssemblyTitle("ValFrames")] [assembly: AssemblyVersion("0.5.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 ValFrames { internal static class FbxReader { public sealed class Skin { public byte[] Colour; public byte[] Normal; } private sealed class Axes { public int Up = 2; public int UpSign = 1; public bool Stated; public Vector3 Scale = Vector3.one; public float Units = 0.01f; } private sealed class Part { public double[] Vertices; public int[] PolygonIndices; public double[] Uvs; public int[] UvIndices; } private sealed class Node { public string Name; public readonly List<object> Properties = new List<object>(); public readonly List<Node> Children = new List<Node>(); } public sealed class Result { public Mesh Mesh; public Bounds PanelBounds; public bool HasPanel; public string TextureName; public readonly List<Skin> Skins = new List<Skin>(); } public enum Front { Read, Forward, Backward, Up, Down, Left, Right } private const string Magic = "Kaydara FBX Binary "; private static readonly char[] Separators = new char[2] { '/', '\\' }; private static readonly char[] Terminator = new char[1]; private const float PanelLift = 0.012f; public static Result Load(string path, float targetWidth, Front front = Front.Read) { //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) try { byte[] data = File.ReadAllBytes(path); if (!Verify(data)) { Log.Warning("Not a binary FBX: " + path); return null; } Node node = Parse(data); List<Part> list = new List<Part>(); Collect(node, list); if (list.Count == 0) { Log.Warning("No mesh found in " + path); return null; } Axes axes = ReadAxes(node); axes.Scale = ReadScale(node); Log.Info(" FBX holds the scene " + ((axes.Up == 1) ? "Y up" : ((axes.Up == 0) ? "X up" : "Z up")) + ((axes.UpSign < 0) ? " (inverted)" : string.Empty) + (axes.Stated ? string.Empty : ", not stated - read as Z up")); Result result = Build(list, targetWidth, front, axes); if (result != null) { result.TextureName = FindTexture(node); CollectSkins(node, result.Skins); for (int i = 0; i < result.Skins.Count; i++) { Skin skin = result.Skins[i]; Log.Info(" FBX material " + i + ": colour " + ((skin.Colour != null) ? (skin.Colour.Length / 1024 + " KB") : "none") + ", normal " + ((skin.Normal != null) ? (skin.Normal.Length / 1024 + " KB") : "none")); } } return result; } catch (Exception ex) { Log.Warning("Could not read " + path + ": " + ex.Message); return null; } } private static void CollectSkins(Node root, List<Skin> skins) { Dictionary<string, byte[]> dictionary = new Dictionary<string, byte[]>(); CollectImages(root, dictionary); List<Node> list = new List<Node>(); CollectNodes(root, "Texture", list); foreach (Node item in list) { string text = FirstString(item) ?? string.Empty; string text2 = BaseName(ChildString(item, "RelativeFilename") ?? ChildString(item, "FileName")); if (text2 == null || !dictionary.TryGetValue(text2, out var value)) { continue; } bool flag = text.IndexOf("normal", StringComparison.OrdinalIgnoreCase) >= 0; if (!flag || skins.Count == 0) { if (!flag) { skins.Add(new Skin { Colour = value }); } } else { skins[skins.Count - 1].Normal = value; } } } private static Axes ReadAxes(Node root) { Axes axes = new Axes(); List<Node> list = new List<Node>(); CollectNodes(root, "P", list); foreach (Node item in list) { switch (FirstString(item)) { case "UpAxis": axes.Up = Whole(item, axes.Up); axes.Stated = true; break; case "UpAxisSign": axes.UpSign = Whole(item, axes.UpSign); break; case "UnitScaleFactor": { float num = (float)Fraction(item, 1.0); if (num > 0f) { axes.Units = num / 100f; } break; } } } return axes; } private static Vector3 ReadScale(Node root) { //IL_014e: 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_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: 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_0154: Unknown result type (might be due to invalid IL or missing references) List<Node> list = new List<Node>(); CollectNodes(root, "Model", list); foreach (Node item in list) { foreach (Node child in item.Children) { if (child.Name != "Properties70") { continue; } foreach (Node child2 in child.Children) { if (!(child2.Name != "P") && !(FirstString(child2) != "Lcl Scaling")) { Vector3 val = Triple(child2); if (val != Vector3.one && val.x > 0f && val.y > 0f && val.z > 0f) { Log.Info(" FBX object scale " + ((Vector3)(ref val)).ToString("0.###") + " applied."); return val; } } } } } return Vector3.one; } private static double Fraction(Node node, double fallback) { for (int num = node.Properties.Count - 1; num >= 0; num--) { object obj = node.Properties[num]; if (obj is double) { return (double)obj; } if (obj is int num2) { return num2; } if (obj is long num3) { return num3; } } return fallback; } private static Vector3 Triple(Node node) { //IL_00a1: 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) List<float> list = new List<float>(3); foreach (object property in node.Properties) { if (property is double num) { list.Add((float)num); } else if (property is int num2) { list.Add(num2); } } if (list.Count < 3) { return Vector3.one; } return new Vector3(list[list.Count - 3], list[list.Count - 2], list[list.Count - 1]); } private static int Whole(Node node, int fallback) { for (int num = node.Properties.Count - 1; num >= 0; num--) { object obj = node.Properties[num]; if (obj is int) { return (int)obj; } if (obj is long num2) { return (int)num2; } if (obj is double num3) { return (int)num3; } } return fallback; } private static void CollectImages(Node node, Dictionary<string, byte[]> images) { if (node.Name == "Video") { string text = BaseName(ChildString(node, "RelativeFilename") ?? ChildString(node, "FileName")); byte[] array = ChildBytes(node, "Content"); if (text != null && array != null && !images.ContainsKey(text)) { images[text] = array; } } foreach (Node child in node.Children) { CollectImages(child, images); } } private static void CollectNodes(Node node, string name, List<Node> found) { if (node.Name == name) { found.Add(node); } foreach (Node child in node.Children) { CollectNodes(child, name, found); } } private static string FirstString(Node node) { foreach (object property in node.Properties) { if (property is string { Length: >0 } text) { return text.Split(Terminator)[0]; } } return null; } private static string ChildString(Node node, string name) { foreach (Node child in node.Children) { if (child.Name == name) { return FirstString(child); } } return null; } private static byte[] ChildBytes(Node node, string name) { foreach (Node child in node.Children) { if (child.Name != name) { continue; } foreach (object property in child.Properties) { if (property is byte[] array && array.Length > 64) { return array; } } } return null; } private static string BaseName(string path) { if (string.IsNullOrEmpty(path)) { return null; } int num = path.LastIndexOfAny(Separators); string text = ((num >= 0) ? path.Substring(num + 1) : path); if (text.Length != 0) { return text; } return null; } private static string FindTexture(Node root) { string found = null; Search(root, ref found); return found; } private static void Search(Node node, ref string found) { if (found != null) { return; } if (node.Name == "RelativeFilename" || node.Name == "FileName") { foreach (object property in node.Properties) { if (property is string { Length: >0 } text) { int num = text.LastIndexOfAny(Separators); string text2 = ((num >= 0) ? text.Substring(num + 1) : text); text2 = text2.Split(Terminator)[0]; if (text2.Length > 0) { found = text2; return; } } } } foreach (Node child in node.Children) { Search(child, ref found); } } private static bool Verify(byte[] data) { if (data.Length < 27) { return false; } for (int i = 0; i < "Kaydara FBX Binary ".Length; i++) { if (data[i] != "Kaydara FBX Binary "[i]) { return false; } } return true; } private static Node Parse(byte[] data) { uint num = BitConverter.ToUInt32(data, 23); Node node = new Node { Name = "root" }; ReadChildren(data, 27, data.Length, num >= 7500, node); return node; } private static void ReadChildren(byte[] data, int position, int end, bool wide, Node parent) { while (position < end) { long num; long num2; if (wide) { num = BitConverter.ToInt64(data, position); num2 = BitConverter.ToInt64(data, position + 8); position += 24; } else { num = BitConverter.ToUInt32(data, position); num2 = BitConverter.ToUInt32(data, position + 4); position += 12; } int num3 = data[position]; position++; if (num == 0L) { break; } Node node = new Node { Name = Encoding.ASCII.GetString(data, position, num3) }; position += num3; for (long num4 = 0L; num4 < num2; num4++) { node.Properties.Add(ReadProperty(data, ref position)); } if (position < num) { ReadChildren(data, position, (int)num, wide, node); } parent.Children.Add(node); position = (int)num; } } private static object ReadProperty(byte[] data, ref int position) { char c = (char)data[position]; position++; switch (c) { case 'Y': { short num8 = BitConverter.ToInt16(data, position); position += 2; return (int)num8; } case 'C': { byte num7 = data[position]; position++; return num7 != 0; } case 'I': { int num6 = BitConverter.ToInt32(data, position); position += 4; return num6; } case 'F': { float num5 = BitConverter.ToSingle(data, position); position += 4; return (double)num5; } case 'D': { double num4 = BitConverter.ToDouble(data, position); position += 8; return num4; } case 'L': { long num3 = BitConverter.ToInt64(data, position); position += 8; return num3; } case 'S': { int num2 = BitConverter.ToInt32(data, position); position += 4; string result = Encoding.UTF8.GetString(data, position, num2); position += num2; return result; } case 'R': { int num = BitConverter.ToInt32(data, position); position += 4; byte[] array = new byte[num]; Buffer.BlockCopy(data, position, array, 0, num); position += num; return array; } case 'f': return ReadArray(data, ref position, 4, doubles: false); case 'd': return ReadArray(data, ref position, 8, doubles: true); case 'i': return ReadIntArray(data, ref position, 4); case 'l': return ReadIntArray(data, ref position, 8); case 'b': return ReadIntArray(data, ref position, 1); default: throw new InvalidDataException("Unknown FBX property type '" + c + "'"); } } private static byte[] RawArray(byte[] data, ref int position, int elementSize, out int count) { count = BitConverter.ToInt32(data, position); int num = BitConverter.ToInt32(data, position + 4); int num2 = BitConverter.ToInt32(data, position + 8); position += 12; byte[] array = new byte[num2]; Buffer.BlockCopy(data, position, array, 0, num2); position += num2; if (num != 1) { return array; } using MemoryStream stream = new MemoryStream(array, 2, array.Length - 2); using DeflateStream deflateStream = new DeflateStream(stream, CompressionMode.Decompress); using MemoryStream memoryStream = new MemoryStream(count * elementSize); byte[] array2 = new byte[8192]; int count2; while ((count2 = deflateStream.Read(array2, 0, array2.Length)) > 0) { memoryStream.Write(array2, 0, count2); } return memoryStream.ToArray(); } private static double[] ReadArray(byte[] data, ref int position, int elementSize, bool doubles) { int count; byte[] value = RawArray(data, ref position, elementSize, out count); double[] array = new double[count]; for (int i = 0; i < count; i++) { array[i] = (doubles ? BitConverter.ToDouble(value, i * 8) : ((double)BitConverter.ToSingle(value, i * 4))); } return array; } private static int[] ReadIntArray(byte[] data, ref int position, int elementSize) { int count; byte[] array = RawArray(data, ref position, elementSize, out count); int[] array2 = new int[count]; for (int i = 0; i < count; i++) { array2[i] = elementSize switch { 4 => BitConverter.ToInt32(array, i * 4), 8 => (int)BitConverter.ToInt64(array, i * 8), _ => array[i], }; } return array2; } private static void Collect(Node node, List<Part> parts) { if (node.Name == "Geometry") { Part part = ReadGeometry(node); if (part != null) { parts.Add(part); } } foreach (Node child in node.Children) { Collect(child, parts); } } private static Part ReadGeometry(Node geometry) { Part part = new Part(); foreach (Node child in geometry.Children) { switch (child.Name) { case "Vertices": part.Vertices = ((child.Properties.Count > 0) ? (child.Properties[0] as double[]) : null); break; case "PolygonVertexIndex": part.PolygonIndices = ((child.Properties.Count > 0) ? (child.Properties[0] as int[]) : null); break; case "LayerElementUV": foreach (Node child2 in child.Children) { if (child2.Name == "UV" && child2.Properties.Count > 0) { part.Uvs = child2.Properties[0] as double[]; } else if (child2.Name == "UVIndex" && child2.Properties.Count > 0) { part.UvIndices = child2.Properties[0] as int[]; } } break; } } if (part.Vertices == null || part.PolygonIndices == null) { return null; } return part; } private static Result Build(List<Part> parts, float targetWidth, Front front, Axes axes) { //IL_0025: 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_0172: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_01cd: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: 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_01e5: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: Unknown result type (might be due to invalid IL or missing references) //IL_030e: Unknown result type (might be due to invalid IL or missing references) //IL_0313: Unknown result type (might be due to invalid IL or missing references) //IL_0320: Expected O, but got Unknown //IL_021b: Unknown result type (might be due to invalid IL or missing references) //IL_0220: Unknown result type (might be due to invalid IL or missing references) //IL_0222: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_0388: Unknown result type (might be due to invalid IL or missing references) //IL_0389: Unknown result type (might be due to invalid IL or missing references) //IL_0297: Unknown result type (might be due to invalid IL or missing references) //IL_02ab: Unknown result type (might be due to invalid IL or missing references) //IL_02b0: Unknown result type (might be due to invalid IL or missing references) //IL_02cb: Unknown result type (might be due to invalid IL or missing references) //IL_02d0: Unknown result type (might be due to invalid IL or missing references) List<Vector3> list = new List<Vector3>(256); List<List<int>> list2 = new List<List<int>>(parts.Count); List<int> list3 = new List<int>(parts.Count); Bounds panelBounds = default(Bounds); bool hasPanel = false; for (int i = 0; i < parts.Count; i++) { Part part = parts[i]; List<int> list4 = new List<int>(part.PolygonIndices.Length * 3); List<int> list5 = new List<int>(8); list3.Add(list.Count); for (int j = 0; j < part.PolygonIndices.Length; j++) { int num = part.PolygonIndices[j]; bool num2 = num < 0; if (num2) { num = ~num; } list.Add(Convert(part.Vertices, num, axes)); list5.Add(list.Count - 1); if (num2) { for (int k = 1; k + 1 < list5.Count; k++) { list4.Add(list5[0]); list4.Add(list5[k + 1]); list4.Add(list5[k]); } list5.Clear(); } } list2.Add(list4); } if (parts.Count > 1) { Face(list, list3[1], (parts.Count > 2) ? list3[2] : list.Count); } else { Turn(list, front); } Bounds val = Extent(list, 0, list.Count); float x = ((Bounds)(ref val)).size.x; if (targetWidth > 0f && x > 0.0001f) { float num3 = targetWidth / x; for (int l = 0; l < list.Count; l++) { list[l] *= num3; } } Bounds val2 = Extent(list, 0, list.Count); Vector3 val3 = default(Vector3); ((Vector3)(ref val3))..ctor(0f - ((Bounds)(ref val2)).center.x, 0f - ((Bounds)(ref val2)).min.y, 0f - ((Bounds)(ref val2)).center.z); if (((Vector3)(ref val3)).sqrMagnitude > 1E-06f) { for (int m = 0; m < list.Count; m++) { list[m] += val3; } Log.Debug(" FBX pivot moved by " + ((Vector3)(ref val3)).ToString("0.000") + " so the model rests on the ground"); } if (parts.Count > 1) { int num4 = list3[1]; int num5 = ((parts.Count > 2) ? list3[2] : list.Count); for (int n = num4; n < num5; n++) { list[n] += new Vector3(0f, 0f, 0.012f); } panelBounds = Extent(list, num4, num5); hasPanel = num5 > num4; Log.Debug(" FBX panel lifted " + 0.012f.ToString("0.000") + " m clear of the body"); } List<Vector2> list6 = FileUvs(parts, list.Count); Mesh val4 = new Mesh { name = "EW_DrawerMesh" }; val4.SetVertices(list); val4.SetUVs(0, list6); val4.subMeshCount = list2.Count; for (int num6 = 0; num6 < list2.Count; num6++) { val4.SetTriangles(list2[num6], num6); } val4.RecalculateNormals(); val4.RecalculateTangents(); val4.RecalculateBounds(); return new Result { Mesh = val4, PanelBounds = panelBounds, HasPanel = hasPanel }; } public static void Reproject(Mesh mesh, float tiles) { if (!((Object)(object)mesh == (Object)null)) { List<Vector3> list = new List<Vector3>(mesh.vertexCount); mesh.GetVertices(list); List<List<int>> list2 = new List<List<int>>(mesh.subMeshCount); for (int i = 0; i < mesh.subMeshCount; i++) { List<int> list3 = new List<int>(); mesh.GetTriangles(list3, i); list2.Add(list3); } mesh.SetUVs(0, PlanarUvs(list, list2, tiles)); } } private static void Turn(List<Vector3> vertices, Front front) { //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) Func<Vector3, Vector3> func; switch (front) { default: return; case Front.Up: func = (Vector3 v) => new Vector3(v.x, 0f - v.z, v.y); break; case Front.Down: func = (Vector3 v) => new Vector3(v.x, v.z, 0f - v.y); break; case Front.Right: func = (Vector3 v) => new Vector3(0f - v.z, v.y, v.x); break; case Front.Left: func = (Vector3 v) => new Vector3(v.z, v.y, 0f - v.x); break; case Front.Backward: func = (Vector3 v) => new Vector3(0f - v.x, v.y, 0f - v.z); break; } for (int num = 0; num < vertices.Count; num++) { vertices[num] = func(vertices[num]); } Log.Debug(" FBX front told as " + front.ToString() + "; turned to face forward."); } private static void Face(List<Vector3> vertices, int from, int to) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: 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_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0079: 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_008e: 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_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: 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_01ee: Unknown result type (might be due to invalid IL or missing references) //IL_0182: 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_019d: 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_0246: 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) if (to <= from) { return; } Bounds val = Extent(vertices, 0, vertices.Count); Bounds val2 = Extent(vertices, from, to); Vector3 val3 = ((Bounds)(ref val2)).center - ((Bounds)(ref val)).center; Vector3 val4 = default(Vector3); ((Vector3)(ref val4))..ctor((((Bounds)(ref val)).size.x > 0.0001f) ? (val3.x / ((Bounds)(ref val)).size.x) : 0f, (((Bounds)(ref val)).size.y > 0.0001f) ? (val3.y / ((Bounds)(ref val)).size.y) : 0f, (((Bounds)(ref val)).size.z > 0.0001f) ? (val3.z / ((Bounds)(ref val)).size.z) : 0f); Func<Vector3, Vector3> func = null; string text = "forward already"; if (Mathf.Abs(val4.y) > Mathf.Abs(val4.x) && Mathf.Abs(val4.y) > Mathf.Abs(val4.z)) { text = ((val4.y > 0f) ? "up" : "down"); func = ((val4.y > 0f) ? ((Func<Vector3, Vector3>)((Vector3 v) => new Vector3(v.x, 0f - v.z, v.y))) : ((Func<Vector3, Vector3>)((Vector3 v) => new Vector3(v.x, v.z, 0f - v.y)))); } else if (Mathf.Abs(val4.x) > Mathf.Abs(val4.z)) { text = ((val4.x > 0f) ? "right" : "left"); func = ((val4.x > 0f) ? ((Func<Vector3, Vector3>)((Vector3 v) => new Vector3(0f - v.z, v.y, v.x))) : ((Func<Vector3, Vector3>)((Vector3 v) => new Vector3(v.z, v.y, 0f - v.x)))); } else if (val4.z < 0f) { text = "backward"; func = (Vector3 v) => new Vector3(0f - v.x, v.y, 0f - v.z); } if (func == null) { Log.Debug(" FBX front: " + text); return; } for (int num = 0; num < vertices.Count; num++) { vertices[num] = func(vertices[num]); } Log.Info("Drawer model was facing " + text + "; turned to face forward."); } private static List<Vector2> FileUvs(List<Part> parts, int total) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) List<Vector2> list = new List<Vector2>(total); foreach (Part part in parts) { for (int i = 0; i < part.PolygonIndices.Length; i++) { list.Add(UvFor(part, i)); } } while (list.Count < total) { list.Add(Vector2.zero); } return list; } private static List<Vector2> PlanarUvs(List<Vector3> vertices, List<List<int>> submeshes, float tiles) { //IL_0011: 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) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: 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_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_007f: 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_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: 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_00b1: 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) List<Vector2> list = new List<Vector2>(vertices.Count); for (int i = 0; i < vertices.Count; i++) { list.Add(Vector2.zero); } foreach (List<int> submesh in submeshes) { for (int j = 0; j + 2 < submesh.Count; j += 3) { Vector3 val = vertices[submesh[j]]; Vector3 val2 = vertices[submesh[j + 1]]; Vector3 val3 = vertices[submesh[j + 2]]; Vector3 normal = Vector3.Cross(val2 - val, val3 - val); for (int k = 0; k < 3; k++) { list[submesh[j + k]] = Project(vertices[submesh[j + k]], normal) * tiles; } } } return list; } private static Vector2 Project(Vector3 point, Vector3 normal) { //IL_0000: 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_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0054: 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) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0042: 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_004e: 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_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) float num = Mathf.Abs(normal.x); float num2 = Mathf.Abs(normal.y); float num3 = Mathf.Abs(normal.z); if (num >= num2 && num >= num3) { return new Vector2(point.z, point.y); } if (!(num2 >= num3)) { return new Vector2(point.x, point.y); } return new Vector2(point.x, point.z); } private static Bounds Extent(List<Vector3> vertices, int from, int to) { //IL_000f: 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_001b: 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_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) if (to <= from || from >= vertices.Count) { return default(Bounds); } Bounds result = default(Bounds); ((Bounds)(ref result))..ctor(vertices[from], Vector3.zero); for (int i = from; i < to && i < vertices.Count; i++) { ((Bounds)(ref result)).Encapsulate(vertices[i]); } return result; } private static Vector3 Convert(double[] source, int index, Axes axes) { //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) int num = index * 3; float num2 = (float)source[num] * axes.Scale.x * axes.Units; float num3 = (float)source[num + 1] * axes.Scale.y * axes.Units; float num4 = (float)source[num + 2] * axes.Scale.z * axes.Units; if (axes.Up == 1) { return new Vector3(0f - num2, (axes.UpSign < 0) ? (0f - num3) : num3, num4); } return new Vector3(0f - num2, (axes.UpSign < 0) ? (0f - num4) : num4, 0f - num3); } private static Vector2 UvFor(Part part, int polygonVertex) { //IL_0008: 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_0061: Unknown result type (might be due to invalid IL or missing references) if (part.Uvs == null) { return Vector2.zero; } int num = ((part.UvIndices == null) ? polygonVertex : ((polygonVertex < part.UvIndices.Length) ? part.UvIndices[polygonVertex] : (-1))); if (num < 0 || num * 2 + 1 >= part.Uvs.Length) { return Vector2.zero; } return new Vector2((float)part.Uvs[num * 2], (float)part.Uvs[num * 2 + 1]); } } internal static class FrameModel { private const string SurfacePiece = "piece_table"; private static readonly string[] Overlays = new string[5] { "snow", "ice", "frost", "wet", "moss" }; private static MethodInfo _loadImage; private static bool _loadImageChecked; public static bool Build(GameObject prefab, string modelFile) { //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_009b: 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) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0101: 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_0117: 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_0142: 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_0167: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) string text = Beside(modelFile); if (text == null || !File.Exists(text)) { Log.Warning("No " + modelFile + " next to the plugin; " + ((Object)prefab).name + " keeps its borrowed look."); return false; } FbxReader.Result result = FbxReader.Load(text, 0f); if (result == null) { return false; } Hang(result.Mesh); Material borrowed = BorrowMaterial(prefab); Strip(prefab); GameObject val = new GameObject("VF_FrameBody"); val.transform.SetParent(prefab.transform, false); val.layer = prefab.layer; MeshFilter val2 = val.AddComponent<MeshFilter>(); MeshRenderer obj = val.AddComponent<MeshRenderer>(); val2.sharedMesh = result.Mesh; ((Renderer)obj).sharedMaterials = Skins(borrowed, result, result.Mesh.subMeshCount); GameObject val3 = new GameObject("VF_FrameCollider"); val3.transform.SetParent(prefab.transform, false); val3.layer = LayerMask.NameToLayer("piece"); Bounds bounds = result.Mesh.bounds; BoxCollider obj2 = val3.AddComponent<BoxCollider>(); obj2.center = ((Bounds)(ref bounds)).center; obj2.size = ((Bounds)(ref bounds)).size; Log.Info(((Object)prefab).name + ": " + ((Bounds)(ref bounds)).size.x.ToString("0.00") + " x " + ((Bounds)(ref bounds)).size.y.ToString("0.00") + " x " + ((Bounds)(ref bounds)).size.z.ToString("0.00") + " m from " + modelFile); return true; } private static void Hang(Mesh mesh) { //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_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) Bounds bounds = mesh.bounds; Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(0f - ((Bounds)(ref bounds)).center.x, 0f - ((Bounds)(ref bounds)).center.y, 0f - ((Bounds)(ref bounds)).min.z); if (!(((Vector3)(ref val)).sqrMagnitude < 1E-06f)) { List<Vector3> list = new List<Vector3>(mesh.vertexCount); mesh.GetVertices(list); for (int i = 0; i < list.Count; i++) { List<Vector3> list2 = list; int index = i; list2[index] += val; } mesh.SetVertices(list); mesh.RecalculateBounds(); } } private static Material[] Skins(Material borrowed, FbxReader.Result model, int count) { Material[] array = (Material[])(object)new Material[Mathf.Max(1, count)]; for (int i = 0; i < array.Length; i++) { FbxReader.Skin obj = ((model.Skins.Count > 0) ? model.Skins[Mathf.Min(i, model.Skins.Count - 1)] : null); Texture2D val = Decode(obj?.Colour, "colour " + i, linear: false); Texture2D relief = Decode(obj?.Normal, "normal " + i, linear: true); array[i] = (((Object)(object)val != (Object)null) ? Painted(borrowed, val, relief) : Plain(borrowed)); } return array; } private static Material Plain(Material template) { //IL_001b: 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_0021: Expected O, but got Unknown Material val = (((Object)(object)template != (Object)null) ? new Material(template) : new Material(Shader.Find("Standard"))); ((Object)val).name = "VF_FramePlain"; if (val.HasProperty("_RippleDistance")) { val.SetFloat("_RippleDistance", 0f); } if (val.HasProperty("_BumpMap")) { val.SetTexture("_BumpMap", (Texture)null); } return val; } private static Material Painted(Material template, Texture2D colour, Texture2D relief) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) Material val = Plain(template); ((Object)val).name = "VF_FramePainted"; val.mainTexture = (Texture)(object)colour; if (val.HasProperty("_Color")) { val.color = Color.white; } if ((Object)(object)relief != (Object)null && val.HasProperty("_BumpMap")) { val.SetTexture("_BumpMap", (Texture)(object)relief); val.EnableKeyword("_NORMALMAP"); } return val; } private static void Strip(GameObject prefab) { MeshRenderer[] componentsInChildren = prefab.GetComponentsInChildren<MeshRenderer>(true); for (int i = 0; i < componentsInChildren.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren[i]); } SkinnedMeshRenderer[] componentsInChildren2 = prefab.GetComponentsInChildren<SkinnedMeshRenderer>(true); for (int i = 0; i < componentsInChildren2.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren2[i]); } MeshFilter[] componentsInChildren3 = prefab.GetComponentsInChildren<MeshFilter>(true); for (int i = 0; i < componentsInChildren3.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren3[i]); } Collider[] componentsInChildren4 = prefab.GetComponentsInChildren<Collider>(true); for (int i = 0; i < componentsInChildren4.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren4[i]); } } private static Material BorrowMaterial(GameObject prefab) { GameObject prefab2 = PrefabManager.Instance.GetPrefab("piece_table"); Material val = (((Object)(object)prefab2 != (Object)null) ? BestMaterial(prefab2) : null); if ((Object)(object)val != (Object)null) { return val; } Log.Warning("No usable material on piece_table; falling back to the item stand's own."); return BestMaterial(prefab); } private static Material BestMaterial(GameObject prefab) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: 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) Material result = null; float num = -1f; MeshRenderer[] componentsInChildren = prefab.GetComponentsInChildren<MeshRenderer>(true); foreach (MeshRenderer val in componentsInChildren) { Material sharedMaterial = ((Renderer)val).sharedMaterial; if (!((Object)(object)sharedMaterial == (Object)null) && !IsOverlay(((Object)sharedMaterial).name)) { Bounds bounds = ((Renderer)val).bounds; Vector3 size = ((Bounds)(ref bounds)).size; float sqrMagnitude = ((Vector3)(ref size)).sqrMagnitude; if (sqrMagnitude > num) { result = sharedMaterial; num = sqrMagnitude; } } } return result; } private static bool IsOverlay(string name) { string[] overlays = Overlays; foreach (string value in overlays) { if (name.IndexOf(value, StringComparison.OrdinalIgnoreCase) >= 0) { return true; } } return false; } private static MethodInfo LoadImageMethod() { if (_loadImageChecked) { return _loadImage; } _loadImageChecked = true; Type type = Type.GetType("UnityEngine.ImageConversion, UnityEngine.ImageConversionModule"); if (type != null) { _loadImage = type.GetMethod("LoadImage", new Type[2] { typeof(Texture2D), typeof(byte[]) }); } if (_loadImage == null) { Log.Warning("Cannot decode images on this build; the frames keep the borrowed surface."); } return _loadImage; } private static Texture2D Decode(byte[] image, string label, bool linear) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown if (image == null) { return null; } MethodInfo methodInfo = LoadImageMethod(); if (methodInfo == null) { return null; } Texture2D val = new Texture2D(2, 2, (TextureFormat)4, true, linear); if (!(bool)methodInfo.Invoke(null, new object[2] { val, image })) { Object.Destroy((Object)(object)val); Log.Warning("An embedded image (" + label + ") could not be read."); return null; } ((Object)val).name = "VF_" + label.Replace(' ', '_'); return val; } public static string Folder() { string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); if (!string.IsNullOrEmpty(directoryName)) { return directoryName; } return null; } public static string Beside(string file) { string text = Folder(); if (text != null) { return Path.Combine(text, file); } return null; } } internal static class Frames { private sealed class Picture { public string Model; public string Prefab; public string English; public string German; } private static readonly string[] Sources = new string[2] { "itemstand", "itemstandh" }; private static readonly Dictionary<string, string> Known = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase) { { "aa", "VF_Frame_AA" }, { "cleo", "VF_Frame_Cleo" }, { "dennis", "VF_Frame_Dennis" }, { "dezzy", "VF_Frame_Dezzy" }, { "dezzyicon", "VF_Frame_DezzyIcon" }, { "exo", "VF_Frame_Exo" } }; private static readonly string[] IconExtensions = new string[3] { ".png", ".jpg", ".jpeg" }; private static List<Picture> Find() { List<Picture> list = new List<Picture>(); string text = FrameModel.Folder(); if (text == null || !Directory.Exists(text)) { return list; } List<string> list2 = new List<string>(Directory.GetFiles(text, "*.fbx")); list2.Sort(StringComparer.OrdinalIgnoreCase); foreach (string item in list2) { string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(item); string text2 = Key(fileNameWithoutExtension); if (text2.Length == 0) { Log.Warning(Path.GetFileName(item) + " has no usable name; skipped."); continue; } string text3 = Title(fileNameWithoutExtension); list.Add(new Picture { Model = Path.GetFileName(item), Prefab = (Known.TryGetValue(text2, out var value) ? value : ("VF_Frame_" + text2)), English = "Framed picture: " + text3, German = "Bild im Rahmen: " + text3 }); } return list; } private static string Key(string name) { StringBuilder stringBuilder = new StringBuilder(); string text = name.ToLowerInvariant(); foreach (char c in text) { if ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9')) { stringBuilder.Append(c); } else if ((c == '_' || c == '-' || c == ' ') && stringBuilder.Length > 0 && stringBuilder[stringBuilder.Length - 1] != '_') { stringBuilder.Append('_'); } } return stringBuilder.ToString().Trim(new char[1] { '_' }); } private static string Title(string name) { string[] array = name.Replace('_', ' ').Replace('-', ' ').Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < array.Length; i++) { array[i] = char.ToUpperInvariant(array[i][0]) + array[i].Substring(1); } return string.Join(" ", array); } private static RequirementConfig[] Cost() { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0018: 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_0027: Expected O, but got Unknown //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: 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_0048: Expected O, but got Unknown return (RequirementConfig[])(object)new RequirementConfig[2] { new RequirementConfig { Item = "FineWood", Amount = 4, Recover = true }, new RequirementConfig { Item = "Resin", Amount = 2, Recover = true } }; } public static void Create() { string text = Source(); if (text == null) { Log.Error("Neither " + string.Join(" nor ", Sources) + " exists in this game; no frames were added."); return; } List<Picture> list = Find(); if (list.Count == 0) { Log.Warning("No .fbx files next to the plugin; no frames were added."); return; } Translate(list); foreach (Picture item in list) { Build(text, item); } } private static string Source() { string[] sources = Sources; foreach (string text in sources) { if ((Object)(object)PrefabManager.Instance.GetPrefab(text) != (Object)null) { Log.Info("Frames are cloned from " + text + "."); return text; } } return null; } private static void Build(string source, Picture picture) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_001b: 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_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Expected O, but got Unknown //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Expected O, but got Unknown PieceConfig val = new PieceConfig { Name = "$" + Token(picture), Description = "$vf_frame_desc", PieceTable = PieceTables.Hammer, Category = "Furniture", CraftingStation = CraftingStations.Workbench, Requirements = Cost(), Icon = Icon(picture.Model) }; CustomPiece val2 = new CustomPiece(picture.Prefab, source, val); if ((Object)(object)val2.PiecePrefab == (Object)null) { Log.Warning("Could not clone " + source + " for " + picture.Prefab + "."); } else { Decorate(val2.PiecePrefab); FrameModel.Build(val2.PiecePrefab, picture.Model); PieceManager.Instance.AddPiece(val2); Log.Info(picture.Prefab + " registered from " + picture.Model + "."); } } private static void Decorate(GameObject prefab) { ItemStand[] componentsInChildren = prefab.GetComponentsInChildren<ItemStand>(true); for (int i = 0; i < componentsInChildren.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren[i]); } } private static string Token(Picture picture) { return "vf_frame_" + Key(Path.GetFileNameWithoutExtension(picture.Model)); } private static Sprite Icon(string modelFile) { string text = Path.GetFileNameWithoutExtension(modelFile) + "_icon"; string text2 = null; string text3 = null; string[] iconExtensions = IconExtensions; foreach (string text4 in iconExtensions) { string text5 = FrameModel.Beside(text + text4); if (text5 != null && File.Exists(text5)) { text2 = text + text4; text3 = text5; break; } } if (text3 == null) { Log.Warning("No " + text + ".png next to the plugin; the build menu shows the default icon."); return null; } Sprite obj = AssetUtils.LoadSpriteFromFile(text3); if ((Object)(object)obj == (Object)null) { Log.Warning(text2 + " could not be read as an icon."); } return obj; } private static void Translate(List<Picture> pictures) { Dictionary<string, string> dictionary = new Dictionary<string, string> { { "vf_frame_desc", "A picture for your wall." } }; Dictionary<string, string> dictionary2 = new Dictionary<string, string> { { "vf_frame_desc", "Ein Bild für deine Wand." } }; foreach (Picture picture in pictures) { dictionary[Token(picture)] = picture.English; dictionary2[Token(picture)] = picture.German; } CustomLocalization localization = LocalizationManager.Instance.GetLocalization(); string text = "English"; localization.AddTranslation(ref text, dictionary); text = "German"; localization.AddTranslation(ref text, dictionary2); } } internal static class Log { private static ManualLogSource _source; public static void Init(ManualLogSource source) { _source = source; } public static void Info(string message) { ManualLogSource source = _source; if (source != null) { source.LogInfo((object)message); } } public static void Warning(string message) { ManualLogSource source = _source; if (source != null) { source.LogWarning((object)message); } } public static void Error(string message) { ManualLogSource source = _source; if (source != null) { source.LogError((object)message); } } public static void Debug(string message) { ManualLogSource source = _source; if (source != null) { source.LogDebug((object)message); } } } [BepInPlugin("dezzycode.valheim.valframes", "ValFrames", "0.5.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] internal sealed class Plugin : BaseUnityPlugin { public const string Guid = "dezzycode.valheim.valframes"; public const string Name = "ValFrames"; public const string Version = "0.5.0"; private void Awake() { Log.Init(((BaseUnityPlugin)this).Logger); PrefabManager.OnVanillaPrefabsAvailable += Create; Log.Info("ValFrames 0.5.0 by DezzyCode loaded."); } private void OnDestroy() { PrefabManager.OnVanillaPrefabsAvailable -= Create; } private void Create() { PrefabManager.OnVanillaPrefabsAvailable -= Create; try { Frames.Create(); } catch (Exception ex) { Log.Error("Could not add the frames: " + ex); } } } }