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 DynamicFurniture v1.0.0
DynamicFurniture.dll
Decompiled 4 days agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using Jotunn; 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.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")] [assembly: AssemblyCompany("DynamicFurniture")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Valheim mod that dynamically loads furniture from OBJ and PNG files at runtime.")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("DynamicFurniture")] [assembly: AssemblyTitle("DynamicFurniture")] [assembly: AssemblyVersion("1.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 DynamicFurniture { [BepInPlugin("com.woltreks.dynamicfurniture", "DynamicFurniture", "1.0.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class DynamicFurniture : BaseUnityPlugin { public const string PluginGUID = "com.woltreks.dynamicfurniture"; public const string PluginName = "DynamicFurniture"; public const string PluginVersion = "1.0.0"; private void Awake() { PrefabManager.OnVanillaPrefabsAvailable += LoadCustomFurniture; Logger.LogInfo((object)"DynamicFurniture mod initialized!"); } private void LoadCustomFurniture() { //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Expected O, but got Unknown //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Expected O, but got Unknown //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: 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_01fe: Unknown result type (might be due to invalid IL or missing references) //IL_0205: Expected O, but got Unknown //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_01c4: Expected O, but got Unknown //IL_021f: Unknown result type (might be due to invalid IL or missing references) //IL_0227: Unknown result type (might be due to invalid IL or missing references) //IL_0231: Unknown result type (might be due to invalid IL or missing references) //IL_0239: Unknown result type (might be due to invalid IL or missing references) //IL_023e: Unknown result type (might be due to invalid IL or missing references) //IL_0248: 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_030e: Unknown result type (might be due to invalid IL or missing references) //IL_027b: Unknown result type (might be due to invalid IL or missing references) //IL_0282: Expected O, but got Unknown //IL_029f: Unknown result type (might be due to invalid IL or missing references) //IL_02b2: Unknown result type (might be due to invalid IL or missing references) //IL_02b7: Unknown result type (might be due to invalid IL or missing references) //IL_0325: Unknown result type (might be due to invalid IL or missing references) //IL_0327: Unknown result type (might be due to invalid IL or missing references) //IL_033d: Unknown result type (might be due to invalid IL or missing references) //IL_0344: Expected O, but got Unknown //IL_0321: 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_03ef: Unknown result type (might be due to invalid IL or missing references) //IL_03f9: Expected O, but got Unknown //IL_03fe: Unknown result type (might be due to invalid IL or missing references) //IL_0405: Expected O, but got Unknown //IL_03c2: Unknown result type (might be due to invalid IL or missing references) //IL_03cc: Expected O, but got Unknown PrefabManager.OnVanillaPrefabsAvailable -= LoadCustomFurniture; string directoryName = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location); Logger.LogInfo((object)("Scanning for custom furniture in: " + directoryName)); if (!Directory.Exists(directoryName)) { return; } GameObject prefab = PrefabManager.Instance.GetPrefab("piece_chair"); Material val = null; if ((Object)(object)prefab != (Object)null) { Renderer componentInChildren = prefab.GetComponentInChildren<Renderer>(); if ((Object)(object)componentInChildren != (Object)null) { val = componentInChildren.sharedMaterial; } } string[] directories = Directory.GetDirectories(directoryName); foreach (string text in directories) { string text2 = Path.Combine(text, "model.obj"); string path = Path.Combine(text, "texture.png"); string path2 = Path.Combine(text, "piece.json"); if (!File.Exists(text2)) { continue; } string fileName = Path.GetFileName(text); Logger.LogInfo((object)("Found model folder: " + fileName)); try { PieceJson pieceJson = new PieceJson(); if (File.Exists(path2)) { pieceJson = PieceJson.Parse(File.ReadAllText(path2)); } else { pieceJson.name = fileName.Replace("_", " "); } Texture2D val2 = null; if (File.Exists(path)) { byte[] array = File.ReadAllBytes(path); val2 = new Texture2D(2, 2); if (!ImageConversion.LoadImage(val2, array)) { Logger.LogWarning((object)("Failed to load image texture for " + fileName)); val2 = null; } } Mesh val3 = ObjLoader.LoadOBJ(text2); if ((Object)(object)val3 == (Object)null) { Logger.LogError((object)("Failed to load OBJ mesh for " + fileName)); continue; } GameObject val4 = new GameObject(fileName); val4.SetActive(false); GameObject val5 = new GameObject("model"); val5.transform.SetParent(val4.transform, false); val5.AddComponent<MeshFilter>().sharedMesh = val3; MeshRenderer obj = val5.AddComponent<MeshRenderer>(); Material val6; if ((Object)(object)val != (Object)null) { val6 = new Material(val); if ((Object)(object)val2 != (Object)null) { val6.mainTexture = (Texture)(object)val2; if (val6.HasProperty("_BumpMap")) { val6.SetTexture("_BumpMap", (Texture)null); } } } else { val6 = new Material(Shader.Find("Standard")); if ((Object)(object)val2 != (Object)null) { val6.mainTexture = (Texture)(object)val2; } } ((Renderer)obj).sharedMaterial = val6; val5.transform.localPosition = pieceJson.offset; val5.transform.localRotation = Quaternion.Euler(pieceJson.rotation); val5.transform.localScale = pieceJson.scale; MeshCollider obj2 = val5.AddComponent<MeshCollider>(); obj2.sharedMesh = val3; obj2.convex = false; if (pieceJson.sittingEnabled) { GameObject val7 = new GameObject("AttachPoint"); val7.transform.SetParent(val4.transform, false); val7.transform.localPosition = pieceJson.sittingPosition; val7.transform.localRotation = Quaternion.Euler(pieceJson.sittingRotation); Chair obj3 = val4.AddComponent<Chair>(); obj3.m_attachPoint = val7.transform; obj3.m_name = "$piece_sit"; } Piece obj4 = val4.AddComponent<Piece>(); obj4.m_name = pieceJson.name; obj4.m_description = pieceJson.description; obj4.m_comfort = pieceJson.comfort; PieceCategory category = (PieceCategory)4; if (Enum.TryParse<PieceCategory>(pieceJson.category, ignoreCase: true, out PieceCategory result)) { category = result; } obj4.m_category = category; val4.AddComponent<WearNTear>().m_health = 50f; PieceConfig val8 = new PieceConfig(); val8.Name = pieceJson.name; val8.Description = pieceJson.description; val8.PieceTable = PieceTables.Hammer; val8.Category = pieceJson.category; val8.CraftingStation = pieceJson.craftingStation; if (pieceJson.cost.Count > 0) { foreach (KeyValuePair<string, int> item in pieceJson.cost) { val8.AddRequirement(new RequirementConfig(item.Key, item.Value, 0, false)); } } else { val8.AddRequirement(new RequirementConfig("Wood", 5, 0, false)); } CustomPiece val9 = new CustomPiece(val4, false, val8); PieceManager.Instance.AddPiece(val9); Logger.LogInfo((object)("Successfully registered custom piece: " + pieceJson.name)); } catch (Exception arg) { Logger.LogError((object)$"Error loading custom furniture from folder {fileName}: {arg}"); } } } } public class PieceJson { public string name = "Custom Furniture"; public string description = "Custom building piece."; public string category = "Furniture"; public string craftingStation = "piece_workbench"; public Dictionary<string, int> cost = new Dictionary<string, int>(); public Vector3 scale = Vector3.one; public Vector3 rotation = Vector3.zero; public Vector3 offset = Vector3.zero; public int comfort; public bool sittingEnabled; public Vector3 sittingPosition = new Vector3(0f, 0.5f, 0f); public Vector3 sittingRotation = Vector3.zero; public static PieceJson Parse(string jsonText) { //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0161: 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_0226: Unknown result type (might be due to invalid IL or missing references) //IL_022b: Unknown result type (might be due to invalid IL or missing references) //IL_0243: Unknown result type (might be due to invalid IL or missing references) //IL_0248: Unknown result type (might be due to invalid IL or missing references) //IL_0260: Unknown result type (might be due to invalid IL or missing references) //IL_0265: Unknown result type (might be due to invalid IL or missing references) PieceJson pieceJson = new PieceJson(); string[] array = jsonText.Split(new char[2] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries); bool flag = false; bool flag2 = false; string[] array2 = array; for (int i = 0; i < array2.Length; i++) { string text = array2[i].Trim(); if (text.Contains("\"cost\":")) { flag = true; continue; } if (text.Contains("\"sitting\":")) { flag2 = true; continue; } if (text == "}," || text == "}") { flag = false; flag2 = false; continue; } int num = text.IndexOf(':'); if (num < 0) { continue; } string text2 = text.Substring(0, num).Replace("\"", "").Trim(); string text3 = text.Substring(num + 1).Replace("\"", "").Trim(); if (text3.EndsWith(",")) { text3 = text3.Substring(0, text3.Length - 1); } if (flag) { if (int.TryParse(text3, out var result)) { pieceJson.cost[text2] = result; } continue; } if (flag2) { switch (text2) { case "enabled": pieceJson.sittingEnabled = text3.ToLower() == "true"; break; case "position": pieceJson.sittingPosition = ParseVector3(text); break; case "rotation": pieceJson.sittingRotation = ParseVector3(text); break; } continue; } switch (text2) { case "name": pieceJson.name = text3; break; case "description": pieceJson.description = text3; break; case "category": pieceJson.category = text3; break; case "crafting_station": pieceJson.craftingStation = text3; break; case "comfort": int.TryParse(text3, out pieceJson.comfort); break; case "scale": pieceJson.scale = ParseVector3(text); break; case "rotation": pieceJson.rotation = ParseVector3(text); break; case "offset": pieceJson.offset = ParseVector3(text); break; } } return pieceJson; } private static Vector3 ParseVector3(string line) { //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) int num = line.IndexOf('['); int num2 = line.IndexOf(']'); if (num >= 0 && num2 > num) { string[] array = line.Substring(num + 1, num2 - num - 1).Split(','); if (array.Length >= 3) { float.TryParse(array[0].Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out var result); float.TryParse(array[1].Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out var result2); float.TryParse(array[2].Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out var result3); return new Vector3(result, result2, result3); } } return Vector3.one; } } public static class ObjLoader { public static Mesh LoadOBJ(string filePath) { //IL_033b: Unknown result type (might be due to invalid IL or missing references) //IL_0342: Expected O, but got Unknown //IL_00e0: 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_0177: 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_01f8: Unknown result type (might be due to invalid IL or missing references) //IL_0244: Unknown result type (might be due to invalid IL or missing references) //IL_0249: Unknown result type (might be due to invalid IL or missing references) //IL_02a3: Unknown result type (might be due to invalid IL or missing references) //IL_02af: Unknown result type (might be due to invalid IL or missing references) //IL_02b8: Unknown result type (might be due to invalid IL or missing references) //IL_023d: Unknown result type (might be due to invalid IL or missing references) //IL_0242: Unknown result type (might be due to invalid IL or missing references) //IL_028e: Unknown result type (might be due to invalid IL or missing references) //IL_0293: Unknown result type (might be due to invalid IL or missing references) if (!File.Exists(filePath)) { return null; } List<Vector3> list = new List<Vector3>(); List<Vector2> list2 = new List<Vector2>(); List<Vector3> list3 = new List<Vector3>(); List<int> list4 = new List<int>(); Dictionary<string, int> dictionary = new Dictionary<string, int>(); List<Vector3> list5 = new List<Vector3>(); List<Vector2> list6 = new List<Vector2>(); List<Vector3> list7 = new List<Vector3>(); string[] array = File.ReadAllLines(filePath); for (int i = 0; i < array.Length; i++) { string text = array[i].Trim(); if (text.StartsWith("#") || string.IsNullOrEmpty(text)) { continue; } string[] array2 = text.Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries); if (array2.Length == 0) { continue; } switch (array2[0]) { case "v": { float num9 = float.Parse(array2[1], CultureInfo.InvariantCulture); float num10 = float.Parse(array2[2], CultureInfo.InvariantCulture); float num11 = float.Parse(array2[3], CultureInfo.InvariantCulture); list.Add(new Vector3(0f - num9, num10, num11)); break; } case "vt": { float num7 = float.Parse(array2[1], CultureInfo.InvariantCulture); float num8 = float.Parse(array2[2], CultureInfo.InvariantCulture); list2.Add(new Vector2(num7, num8)); break; } case "vn": { float num4 = float.Parse(array2[1], CultureInfo.InvariantCulture); float num5 = float.Parse(array2[2], CultureInfo.InvariantCulture); float num6 = float.Parse(array2[3], CultureInfo.InvariantCulture); list3.Add(new Vector3(0f - num4, num5, num6)); break; } case "f": { List<int> list8 = new List<int>(); for (int j = 1; j < array2.Length; j++) { string text2 = array2[j]; if (dictionary.TryGetValue(text2, out var value)) { list8.Add(value); continue; } string[] array3 = text2.Split('/'); int num = int.Parse(array3[0]) - 1; if (num < 0) { num = list.Count + num + 1; } Vector2 item = Vector2.zero; if (array3.Length > 1 && !string.IsNullOrEmpty(array3[1])) { int num2 = int.Parse(array3[1]) - 1; if (num2 < 0) { num2 = list2.Count + num2 + 1; } if (num2 >= 0 && num2 < list2.Count) { item = list2[num2]; } } Vector3 item2 = Vector3.zero; if (array3.Length > 2 && !string.IsNullOrEmpty(array3[2])) { int num3 = int.Parse(array3[2]) - 1; if (num3 < 0) { num3 = list3.Count + num3 + 1; } if (num3 >= 0 && num3 < list3.Count) { item2 = list3[num3]; } } int count = list5.Count; list5.Add(list[num]); list6.Add(item); list7.Add(item2); dictionary[text2] = count; list8.Add(count); } for (int k = 1; k < list8.Count - 1; k++) { list4.Add(list8[0]); list4.Add(list8[k + 1]); list4.Add(list8[k]); } break; } } } Mesh val = new Mesh(); val.vertices = list5.ToArray(); val.uv = list6.ToArray(); if (list7.Count > 0) { val.normals = list7.ToArray(); } else { val.RecalculateNormals(); } val.triangles = list4.ToArray(); val.RecalculateBounds(); val.RecalculateTangents(); return val; } } }