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 ValheimDBDumper v1.0.0
ValheimDBDumper.dll
Decompiled 8 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; 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.Security; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using UnityEngine; using ValheimDBDumper.Tools; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.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 ValheimDBDumper { public class PrefabNode { public string object_name { get; set; } public bool is_active { get; set; } public string layer { get; set; } public string tag { get; set; } public List<ComponentData> components { get; set; } = new List<ComponentData>(); public List<PrefabNode> children { get; set; } = new List<PrefabNode>(); } public class ComponentData { public string type { get; set; } public Dictionary<string, string> fields { get; set; } = new Dictionary<string, string>(); } public class CreatureDataDump { public string prefab_name { get; set; } public string creature_name { get; set; } public string creature_rawName { get; set; } public float max_health { get; set; } public string faction { get; set; } public bool tolerate_water { get; set; } public bool tolerate_fire { get; set; } public List<CreatureDropData> drops { get; set; } = new List<CreatureDropData>(); } public class CreatureDropData { public string item_prefab { get; set; } public int min_amount { get; set; } public int max_amount { get; set; } public float chance_percent { get; set; } public bool level_multiplier { get; set; } } public static class CreaturesExporter { [CompilerGenerated] private sealed class <ExportCreaturesCoroutine>d__0 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public string baseFolder; public ConsoleEventArgs args; public bool exportJson; public bool exportIcons; public bool exportPrefab; public bool exportModel3d; public Action onFinished; private string <creaturesFolder>5__1; private string <iconsFolder>5__2; private string <prefabsFolder>5__3; private string <modelsFolder>5__4; private string <texturesFolder>5__5; private List<GameObject> <allPrefabs>5__6; private List<CreatureDataDump> <exportedCreatures>5__7; private int <operationsThisFrame>5__8; private int <i>5__9; private GameObject <prefab>5__10; private Character <character>5__11; private string <prefabName>5__12; private string <creatureRawName>5__13; private CharacterDrop <dropComponent>5__14; private List<Drop>.Enumerator <>s__15; private Drop <drop>5__16; private ItemDrop <trophyItem>5__17; private CreatureDataDump <data>5__18; private List<Drop>.Enumerator <>s__19; private Drop <drop>5__20; private string <targetFile>5__21; private string <targetObjPath>5__22; private string <jsonOutput>5__23; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <ExportCreaturesCoroutine>d__0(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <creaturesFolder>5__1 = null; <iconsFolder>5__2 = null; <prefabsFolder>5__3 = null; <modelsFolder>5__4 = null; <texturesFolder>5__5 = null; <allPrefabs>5__6 = null; <exportedCreatures>5__7 = null; <prefab>5__10 = null; <character>5__11 = null; <prefabName>5__12 = null; <creatureRawName>5__13 = null; <dropComponent>5__14 = null; <>s__15 = default(List<Drop>.Enumerator); <drop>5__16 = null; <trophyItem>5__17 = null; <data>5__18 = null; <>s__19 = default(List<Drop>.Enumerator); <drop>5__20 = null; <targetFile>5__21 = null; <targetObjPath>5__22 = null; <jsonOutput>5__23 = null; <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <creaturesFolder>5__1 = Path.Combine(baseFolder, "data", "creatures"); <iconsFolder>5__2 = Path.Combine(baseFolder, "icons"); <prefabsFolder>5__3 = Path.Combine(baseFolder, "prefabs", "creatures"); <modelsFolder>5__4 = Path.Combine(baseFolder, "models", "creatures"); <texturesFolder>5__5 = Path.Combine(baseFolder, "textures", "creatures"); if (exportJson) { Directory.CreateDirectory(<creaturesFolder>5__1); } if (exportIcons) { Directory.CreateDirectory(<iconsFolder>5__2); } if (exportPrefab) { Directory.CreateDirectory(<prefabsFolder>5__3); } if (exportModel3d) { Directory.CreateDirectory(<modelsFolder>5__4); Directory.CreateDirectory(<texturesFolder>5__5); } <allPrefabs>5__6 = ZNetScene.instance.m_prefabs; <exportedCreatures>5__7 = new List<CreatureDataDump>(); args.Context.AddString($"<color=yellow>[Valheim DBDumper] Scanning {<allPrefabs>5__6.Count} game prefabs for creatures...</color>"); LogSystem.Info($"Scanning {<allPrefabs>5__6.Count} game prefabs for creatures..."); <>2__current = null; <>1__state = 1; return true; case 1: <>1__state = -1; <operationsThisFrame>5__8 = 0; <i>5__9 = 0; goto IL_0785; case 2: { <>1__state = -1; goto IL_074f; } IL_0785: if (<i>5__9 < <allPrefabs>5__6.Count) { <prefab>5__10 = <allPrefabs>5__6[<i>5__9]; if (!((Object)(object)<prefab>5__10 == (Object)null)) { <character>5__11 = <prefab>5__10.GetComponent<Character>(); if (!((Object)(object)<character>5__11 == (Object)null)) { <prefabName>5__12 = ((Object)<prefab>5__10).name; <creatureRawName>5__13 = <character>5__11.m_name; if (!<prefabName>5__12.ToLower().Contains("player")) { <dropComponent>5__14 = <prefab>5__10.GetComponent<CharacterDrop>(); if (exportIcons && (Object)(object)<dropComponent>5__14 != (Object)null && <dropComponent>5__14.m_drops != null) { Directory.CreateDirectory(Path.Combine(<iconsFolder>5__2, "Creatures")); <>s__15 = <dropComponent>5__14.m_drops.GetEnumerator(); try { while (<>s__15.MoveNext()) { <drop>5__16 = <>s__15.Current; if ((Object)(object)<drop>5__16.m_prefab != (Object)null && ((Object)<drop>5__16.m_prefab).name.ToLower().Contains("trophy")) { <trophyItem>5__17 = <drop>5__16.m_prefab.GetComponent<ItemDrop>(); if ((Object)(object)<trophyItem>5__17 != (Object)null) { ItemData itemData = <trophyItem>5__17.m_itemData; if (itemData != null && itemData.m_shared?.m_icons?.Length > 0) { SaveCroppedSpriteAsPNG(<trophyItem>5__17.m_itemData.m_shared.m_icons[0], Path.Combine(<iconsFolder>5__2, "Creatures", <prefabName>5__12 + ".png")); <operationsThisFrame>5__8++; break; } } <trophyItem>5__17 = null; } <drop>5__16 = null; } } finally { ((IDisposable)<>s__15).Dispose(); } <>s__15 = default(List<Drop>.Enumerator); } if (exportJson) { <data>5__18 = new CreatureDataDump { prefab_name = <prefabName>5__12, creature_name = TranslateToken(<creatureRawName>5__13), creature_rawName = <creatureRawName>5__13, max_health = <character>5__11.m_health, faction = ((object)(Faction)(ref <character>5__11.m_faction)).ToString(), tolerate_water = <character>5__11.m_tolerateWater, tolerate_fire = <character>5__11.m_tolerateFire }; if ((Object)(object)<dropComponent>5__14 != (Object)null && <dropComponent>5__14.m_drops != null) { <>s__19 = <dropComponent>5__14.m_drops.GetEnumerator(); try { while (<>s__19.MoveNext()) { <drop>5__20 = <>s__19.Current; if (<drop>5__20 != null && !((Object)(object)<drop>5__20.m_prefab == (Object)null)) { <data>5__18.drops.Add(new CreatureDropData { item_prefab = ((Object)<drop>5__20.m_prefab).name, min_amount = <drop>5__20.m_amountMin, max_amount = <drop>5__20.m_amountMax, chance_percent = <drop>5__20.m_chance * 100f, level_multiplier = <drop>5__20.m_levelMultiplier }); <drop>5__20 = null; } } } finally { ((IDisposable)<>s__19).Dispose(); } <>s__19 = default(List<Drop>.Enumerator); } <exportedCreatures>5__7.Add(<data>5__18); <data>5__18 = null; } if (exportPrefab) { <targetFile>5__21 = Path.Combine(<prefabsFolder>5__3, <prefabName>5__12 + ".json"); DumpPrefabHierarchyToJson(<prefab>5__10, <targetFile>5__21); <operationsThisFrame>5__8++; <targetFile>5__21 = null; } if (exportModel3d) { <targetObjPath>5__22 = Path.Combine(<modelsFolder>5__4, <prefabName>5__12 + ".obj"); ExportPrefabToObj(<prefab>5__10, <targetObjPath>5__22); ExportCreatureSkinTexture(<prefab>5__10, <texturesFolder>5__5, <prefabName>5__12); <operationsThisFrame>5__8++; <targetObjPath>5__22 = null; } if (<exportedCreatures>5__7.Count % 20 == 0) { args.Context.AddString($"<color=#00FFD9>[Valheim DBDumper] Processed {<exportedCreatures>5__7.Count} unique creatures...</color>"); } if (<operationsThisFrame>5__8 >= 30) { <operationsThisFrame>5__8 = 0; <>2__current = null; <>1__state = 2; return true; } goto IL_074f; } } } goto IL_0773; } if (exportJson && <exportedCreatures>5__7.Count > 0) { <jsonOutput>5__23 = JsonConvert.SerializeObject((object)<exportedCreatures>5__7, (Formatting)1); File.WriteAllText(Path.Combine(<creaturesFolder>5__1, "creatures.json"), <jsonOutput>5__23); <jsonOutput>5__23 = null; } args.Context.AddString("<color=green>[Valheim DBDumper] Creatures module finished! Geometries and skin textures successfully dumped.</color>"); LogSystem.Success("Creatures module finished! Geometries and skin textures successfully dumped."); onFinished?.Invoke(); return false; IL_0773: <i>5__9++; goto IL_0785; IL_074f: <prefab>5__10 = null; <character>5__11 = null; <prefabName>5__12 = null; <creatureRawName>5__13 = null; <dropComponent>5__14 = null; goto IL_0773; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [IteratorStateMachine(typeof(<ExportCreaturesCoroutine>d__0))] public static IEnumerator ExportCreaturesCoroutine(string baseFolder, ConsoleEventArgs args, bool exportJson, bool exportIcons, bool exportPrefab, bool exportModel3d, Action onFinished) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <ExportCreaturesCoroutine>d__0(0) { baseFolder = baseFolder, args = args, exportJson = exportJson, exportIcons = exportIcons, exportPrefab = exportPrefab, exportModel3d = exportModel3d, onFinished = onFinished }; } private static void ExportCreatureSkinTexture(GameObject prefab, string texturesFolder, string prefabName) { string text = Path.Combine(texturesFolder, prefabName + ".png"); if (File.Exists(text)) { return; } Renderer[] componentsInChildren = prefab.GetComponentsInChildren<Renderer>(true); Renderer[] array = componentsInChildren; foreach (Renderer val in array) { if (!((Object)(object)val == (Object)null) && !((Object)(object)val.material == (Object)null)) { Texture val2 = val.material.mainTexture; if ((Object)(object)val2 == (Object)null && val.material.HasProperty("_MainTex")) { val2 = val.material.GetTexture("_MainTex"); } if ((Object)(object)val2 != (Object)null && val2.width > 32 && val2.height > 32) { SaveRuntimeTextureAsPNG(val2, text); break; } } } } private static void SaveRuntimeTextureAsPNG(Texture srcTexture, string outputPath) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown //IL_004b: Unknown result type (might be due to invalid IL or missing references) try { int width = srcTexture.width; int height = srcTexture.height; RenderTexture temporary = RenderTexture.GetTemporary(width, height, 0, (RenderTextureFormat)7, (RenderTextureReadWrite)1); Graphics.Blit(srcTexture, temporary); RenderTexture active = RenderTexture.active; RenderTexture.active = temporary; Texture2D val = new Texture2D(width, height, (TextureFormat)4, false); val.ReadPixels(new Rect(0f, 0f, (float)width, (float)height), 0, 0); val.Apply(); RenderTexture.active = active; RenderTexture.ReleaseTemporary(temporary); byte[] bytes = ImageConversion.EncodeToPNG(val); File.WriteAllBytes(outputPath, bytes); Object.Destroy((Object)(object)val); } catch (Exception ex) { LogSystem.Error("Error saving creature skin texture: " + ex.Message + "\n"); } } private static void DumpPrefabHierarchyToJson(GameObject prefab, string outputPath) { try { PrefabNode prefabNode = BuildPrefabNodeElement(prefab.transform); string contents = JsonConvert.SerializeObject((object)prefabNode, (Formatting)1); File.WriteAllText(outputPath, contents); } catch (Exception ex) { LogSystem.Error("Error dumping prefab hierarchy: " + ex.Message); } } private static PrefabNode BuildPrefabNodeElement(Transform current) { PrefabNode prefabNode = new PrefabNode { object_name = ((Object)current).name, is_active = ((Component)current).gameObject.activeSelf, layer = LayerMask.LayerToName(((Component)current).gameObject.layer), tag = ((Component)current).gameObject.tag }; Component[] components = ((Component)current).GetComponents<Component>(); Component[] array = components; foreach (Component val in array) { if ((Object)(object)val == (Object)null) { continue; } ComponentData componentData = new ComponentData { type = ((object)val).GetType().Name }; if (val is Character || val is Humanoid || val is MonsterAI) { FieldInfo[] fields = ((object)val).GetType().GetFields(BindingFlags.Instance | BindingFlags.Public); FieldInfo[] array2 = fields; foreach (FieldInfo fieldInfo in array2) { try { object value = fieldInfo.GetValue(val); if (value != null && !(value is GameObject) && !(value is Component)) { componentData.fields[fieldInfo.Name] = value.ToString(); } } catch (Exception ex) { LogSystem.Error("Error getting field value: " + ex.Message); } } } prefabNode.components.Add(componentData); } for (int k = 0; k < current.childCount; k++) { prefabNode.children.Add(BuildPrefabNodeElement(current.GetChild(k))); } return prefabNode; } private static void ExportPrefabToObj(GameObject prefab, string outputPath) { //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: 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_0106: 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_0041: 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_008d: Expected O, but got Unknown //IL_0098: 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_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_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Unknown result type (might be due to invalid IL or missing references) //IL_018f: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_01a5: Unknown result type (might be due to invalid IL or missing references) if (File.Exists(outputPath)) { return; } try { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine("# Valheim DBDumper - 3D Mesh of " + ((Object)prefab).name); int vOffset = 1; int nOffset = 1; int uvOffset = 1; Matrix4x4 worldToLocalMatrix = prefab.transform.worldToLocalMatrix; SkinnedMeshRenderer[] componentsInChildren = prefab.GetComponentsInChildren<SkinnedMeshRenderer>(true); SkinnedMeshRenderer[] array = componentsInChildren; foreach (SkinnedMeshRenderer val in array) { if ((Object)(object)val == (Object)null || (Object)(object)val.sharedMesh == (Object)null) { continue; } Mesh val2 = new Mesh(); try { val.BakeMesh(val2); Matrix4x4 localToRoot = worldToLocalMatrix * ((Component)val).transform.localToWorldMatrix; ProcessMeshAsset(val2, ((Object)val).name, stringBuilder, localToRoot, ref vOffset, ref nOffset, ref uvOffset); } catch (Exception ex) { LogSystem.Warn("Error baking mesh: " + ex.Message); Matrix4x4 localToRoot2 = worldToLocalMatrix * ((Component)val).transform.localToWorldMatrix; ProcessMeshAsset(val.sharedMesh, ((Object)val).name, stringBuilder, localToRoot2, ref vOffset, ref nOffset, ref uvOffset); } finally { if ((Object)(object)val2 != (Object)null) { Object.Destroy((Object)(object)val2); } } } MeshFilter[] componentsInChildren2 = prefab.GetComponentsInChildren<MeshFilter>(true); MeshFilter[] array2 = componentsInChildren2; foreach (MeshFilter val3 in array2) { if (!((Object)(object)val3 == (Object)null) && !((Object)(object)val3.sharedMesh == (Object)null)) { Matrix4x4 localToRoot3 = worldToLocalMatrix * ((Component)val3).transform.localToWorldMatrix; ProcessMeshAsset(val3.sharedMesh, ((Object)val3).name, stringBuilder, localToRoot3, ref vOffset, ref nOffset, ref uvOffset); } } if (vOffset > 1) { File.WriteAllText(outputPath, stringBuilder.ToString()); } } catch (Exception ex2) { LogSystem.Error("Error exporting prefab to OBJ: " + ex2.Message); } } private static void ProcessMeshAsset(Mesh mesh, string name, StringBuilder sb, Matrix4x4 localToRoot, ref int vOffset, ref int nOffset, ref int uvOffset) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: 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_004c: 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_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: 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_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: 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_00f7: 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_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0108: 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_0120: Unknown result type (might be due to invalid IL or missing references) sb.AppendLine("\ng " + name); Vector3[] vertices = mesh.vertices; Vector3[] array = vertices; foreach (Vector3 val in array) { Vector3 val2 = ((Matrix4x4)(ref localToRoot)).MultiplyPoint3x4(val); sb.AppendLine($"v {val2.x} {val2.y} {val2.z}"); } Vector2[] uv = mesh.uv; Vector2[] array2 = uv; foreach (Vector2 val3 in array2) { sb.AppendLine($"vt {val3.x} {val3.y}"); } Vector3[] normals = mesh.normals; Vector3[] array3 = normals; foreach (Vector3 val4 in array3) { Vector3 val5 = ((Matrix4x4)(ref localToRoot)).MultiplyVector(val4); Vector3 normalized = ((Vector3)(ref val5)).normalized; sb.AppendLine($"vn {normalized.x} {normalized.y} {normalized.z}"); } bool flag = uv.Length != 0; bool flag2 = normals.Length != 0; for (int l = 0; l < mesh.subMeshCount; l++) { int[] triangles = mesh.GetTriangles(l); for (int m = 0; m < triangles.Length; m += 3) { int num = triangles[m] + vOffset; int num2 = triangles[m + 1] + vOffset; int num3 = triangles[m + 2] + vOffset; int num4 = triangles[m] + uvOffset; int num5 = triangles[m + 1] + uvOffset; int num6 = triangles[m + 2] + uvOffset; int num7 = triangles[m] + nOffset; int num8 = triangles[m + 1] + nOffset; int num9 = triangles[m + 2] + nOffset; if (flag && flag2) { sb.AppendLine($"f {num3}/{num6}/{num9} {num2}/{num5}/{num8} {num}/{num4}/{num7}"); } else if (flag) { sb.AppendLine($"f {num3}/{num6} {num2}/{num5} {num}/{num4}"); } else if (flag2) { sb.AppendLine($"f {num3}//{num9} {num2}//{num8} {num}//{num7}"); } else { sb.AppendLine($"f {num3} {num2} {num}"); } } } vOffset += vertices.Length; uvOffset += uv.Length; nOffset += normals.Length; } private static string TranslateToken(string token) { if (string.IsNullOrEmpty(token)) { return ""; } if (!token.StartsWith("$")) { return token; } try { Type type = typeof(Terminal).Assembly.GetType("Localization") ?? Type.GetType("Valheim.Localization, assembly_valheim"); if (type == null) { return token; } object obj = type.GetProperty("instance", BindingFlags.Static | BindingFlags.Public)?.GetValue(null); if (obj == null) { return token; } return (type.GetMethod("Localize", new Type[1] { typeof(string) })?.Invoke(obj, new object[1] { token }) as string) ?? token; } catch (Exception ex) { LogSystem.Error("Error translating token: " + ex.Message); return token; } } private static void SaveCroppedSpriteAsPNG(Sprite sprite, string outputPath) { //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_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Expected O, but got Unknown //IL_0094: Unknown result type (might be due to invalid IL or missing references) if (File.Exists(outputPath)) { return; } try { Texture2D texture = sprite.texture; if (!((Object)(object)texture == (Object)null)) { Rect textureRect = sprite.textureRect; int num = (int)((Rect)(ref textureRect)).width; int num2 = (int)((Rect)(ref textureRect)).height; RenderTexture temporary = RenderTexture.GetTemporary(((Texture)texture).width, ((Texture)texture).height, 0, (RenderTextureFormat)7, (RenderTextureReadWrite)1); Graphics.Blit((Texture)(object)texture, temporary); RenderTexture active = RenderTexture.active; RenderTexture.active = temporary; Texture2D val = new Texture2D(num, num2, (TextureFormat)4, false); val.ReadPixels(new Rect(((Rect)(ref textureRect)).x, ((Rect)(ref textureRect)).y, (float)num, (float)num2), 0, 0); val.Apply(); RenderTexture.active = active; RenderTexture.ReleaseTemporary(temporary); byte[] bytes = ImageConversion.EncodeToPNG(val); File.WriteAllBytes(outputPath, bytes); Object.Destroy((Object)(object)val); } } catch (Exception ex) { LogSystem.Error("Error saving creature skin texture: " + ex.Message); } } } public class ItemDataDump { public string prefab_name { get; set; } public string item_name { get; set; } public string item_rawName { get; set; } public string description { get; set; } public string type { get; set; } public float weight { get; set; } public int max_stack { get; set; } public float max_durability { get; set; } public float armor { get; set; } public float blunt_damage { get; set; } public float slash_damage { get; set; } public float pierce_damage { get; set; } public float chop_damage { get; set; } public float pickaxe_damage { get; set; } public float fire_damage { get; set; } public float frost_damage { get; set; } public float lightning_damage { get; set; } public float poison_damage { get; set; } public float spirit_damage { get; set; } } public static class ItemsExporter { [CompilerGenerated] private sealed class <ExportItemsCoroutine>d__0 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public string baseFolder; public ConsoleEventArgs args; public bool exportJson; public bool exportIcons; public bool exportPrefab; public bool exportModel3d; public Action onFinished; private string <itemsFolder>5__1; private string <iconsFolder>5__2; private string <prefabsFolder>5__3; private string <modelsFolder>5__4; private string <texturesFolder>5__5; private List<GameObject> <itemPrefabs>5__6; private List<ItemDataDump> <exportedItems>5__7; private int <operationsThisFrame>5__8; private int <i>5__9; private GameObject <prefab>5__10; private ItemDrop <itemDrop>5__11; private SharedData <shared>5__12; private string <prefabName>5__13; private Sprite[] <iconsArray>5__14; private ItemDataDump <data>5__15; private string <targetFile>5__16; private string <targetObjPath>5__17; private string <jsonOutput>5__18; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <ExportItemsCoroutine>d__0(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <itemsFolder>5__1 = null; <iconsFolder>5__2 = null; <prefabsFolder>5__3 = null; <modelsFolder>5__4 = null; <texturesFolder>5__5 = null; <itemPrefabs>5__6 = null; <exportedItems>5__7 = null; <prefab>5__10 = null; <itemDrop>5__11 = null; <shared>5__12 = null; <prefabName>5__13 = null; <iconsArray>5__14 = null; <data>5__15 = null; <targetFile>5__16 = null; <targetObjPath>5__17 = null; <jsonOutput>5__18 = null; <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <itemsFolder>5__1 = Path.Combine(baseFolder, "data", "items"); <iconsFolder>5__2 = Path.Combine(baseFolder, "icons"); <prefabsFolder>5__3 = Path.Combine(baseFolder, "prefabs", "items"); <modelsFolder>5__4 = Path.Combine(baseFolder, "models", "items"); <texturesFolder>5__5 = Path.Combine(baseFolder, "textures", "items"); if (exportJson) { Directory.CreateDirectory(<itemsFolder>5__1); } if (exportIcons) { Directory.CreateDirectory(<iconsFolder>5__2); } if (exportPrefab) { Directory.CreateDirectory(<prefabsFolder>5__3); } if (exportModel3d) { Directory.CreateDirectory(<modelsFolder>5__4); Directory.CreateDirectory(<texturesFolder>5__5); } <itemPrefabs>5__6 = ObjectDB.instance.m_items; <exportedItems>5__7 = new List<ItemDataDump>(); args.Context.AddString($"<color=yellow>[Valheim DBDumper] Processing {<itemPrefabs>5__6.Count} items into unified pipeline...</color>"); LogSystem.Info($"Processing {<itemPrefabs>5__6.Count} items into unified pipeline..."); <>2__current = null; <>1__state = 1; return true; case 1: <>1__state = -1; <operationsThisFrame>5__8 = 0; <i>5__9 = 0; goto IL_0639; case 2: { <>1__state = -1; goto IL_060a; } IL_0639: if (<i>5__9 < <itemPrefabs>5__6.Count) { <prefab>5__10 = <itemPrefabs>5__6[<i>5__9]; if (!((Object)(object)<prefab>5__10 == (Object)null)) { <itemDrop>5__11 = <prefab>5__10.GetComponent<ItemDrop>(); if (!((Object)(object)<itemDrop>5__11 == (Object)null) && <itemDrop>5__11.m_itemData != null) { <shared>5__12 = <itemDrop>5__11.m_itemData.m_shared; <prefabName>5__13 = ((Object)<prefab>5__10).name; if (exportIcons) { Directory.CreateDirectory(Path.Combine(<iconsFolder>5__2, "Items")); <iconsArray>5__14 = <shared>5__12.m_icons; if (<iconsArray>5__14 != null && <iconsArray>5__14.Length != 0 && (Object)(object)<iconsArray>5__14[0] != (Object)null) { SaveCroppedSpriteAsPNG(<iconsArray>5__14[0], Path.Combine(<iconsFolder>5__2, "Items", <prefabName>5__13 + ".png")); <operationsThisFrame>5__8++; } <iconsArray>5__14 = null; } if (exportJson) { <data>5__15 = new ItemDataDump { prefab_name = <prefabName>5__13, item_name = TranslateToken(<shared>5__12.m_name), item_rawName = <shared>5__12.m_name, description = TranslateToken(<shared>5__12.m_description), type = ((object)(ItemType)(ref <shared>5__12.m_itemType)).ToString(), weight = <shared>5__12.m_weight, max_stack = <shared>5__12.m_maxStackSize, max_durability = <shared>5__12.m_maxDurability, armor = <shared>5__12.m_armor, blunt_damage = <shared>5__12.m_damages.m_blunt, slash_damage = <shared>5__12.m_damages.m_slash, pierce_damage = <shared>5__12.m_damages.m_pierce, chop_damage = <shared>5__12.m_damages.m_chop, pickaxe_damage = <shared>5__12.m_damages.m_pickaxe, fire_damage = <shared>5__12.m_damages.m_fire, frost_damage = <shared>5__12.m_damages.m_frost, lightning_damage = <shared>5__12.m_damages.m_lightning, poison_damage = <shared>5__12.m_damages.m_poison, spirit_damage = <shared>5__12.m_damages.m_spirit }; <exportedItems>5__7.Add(<data>5__15); <data>5__15 = null; } if (exportPrefab) { <targetFile>5__16 = Path.Combine(<prefabsFolder>5__3, <prefabName>5__13 + ".json"); DumpPrefabHierarchyToJson(<prefab>5__10, <targetFile>5__16); <operationsThisFrame>5__8++; <targetFile>5__16 = null; } if (exportModel3d) { <targetObjPath>5__17 = Path.Combine(<modelsFolder>5__4, <prefabName>5__13 + ".obj"); ExportPrefabToObj(<prefab>5__10, <targetObjPath>5__17); ExportItemSkinTexture(<prefab>5__10, <texturesFolder>5__5, <prefabName>5__13); <operationsThisFrame>5__8++; <targetObjPath>5__17 = null; } if (<i>5__9 > 0 && <i>5__9 % 150 == 0) { args.Context.AddString($"<color=lightblue>[Valheim DBDumper] Processed {<i>5__9}/{<itemPrefabs>5__6.Count} unique items...</color>"); } if (<operationsThisFrame>5__8 >= 25) { <operationsThisFrame>5__8 = 0; <>2__current = null; <>1__state = 2; return true; } goto IL_060a; } } goto IL_0627; } if (exportJson && <exportedItems>5__7.Count > 0) { <jsonOutput>5__18 = JsonConvert.SerializeObject((object)<exportedItems>5__7, (Formatting)1); File.WriteAllText(Path.Combine(<itemsFolder>5__1, "items.json"), <jsonOutput>5__18); <jsonOutput>5__18 = null; } args.Context.AddString("<color=green>[Valheim DBDumper] Item module finished processing successfully! Models and textures sync'd.</color>"); LogSystem.Success("Item module finished processing successfully! Models and textures sync'd."); onFinished?.Invoke(); return false; IL_060a: <prefab>5__10 = null; <itemDrop>5__11 = null; <shared>5__12 = null; <prefabName>5__13 = null; goto IL_0627; IL_0627: <i>5__9++; goto IL_0639; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [IteratorStateMachine(typeof(<ExportItemsCoroutine>d__0))] public static IEnumerator ExportItemsCoroutine(string baseFolder, ConsoleEventArgs args, bool exportJson, bool exportIcons, bool exportPrefab, bool exportModel3d, Action onFinished) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <ExportItemsCoroutine>d__0(0) { baseFolder = baseFolder, args = args, exportJson = exportJson, exportIcons = exportIcons, exportPrefab = exportPrefab, exportModel3d = exportModel3d, onFinished = onFinished }; } private static void DumpPrefabHierarchyToJson(GameObject prefab, string outputPath) { try { PrefabNode prefabNode = BuildPrefabNodeElement(prefab.transform); string contents = JsonConvert.SerializeObject((object)prefabNode, (Formatting)1); File.WriteAllText(outputPath, contents); } catch (Exception ex) { LogSystem.Error("Error dumping prefab hierarchy: " + ex.Message); } } private static PrefabNode BuildPrefabNodeElement(Transform current) { PrefabNode prefabNode = new PrefabNode { object_name = ((Object)current).name, is_active = ((Component)current).gameObject.activeSelf, layer = LayerMask.LayerToName(((Component)current).gameObject.layer), tag = ((Component)current).gameObject.tag }; Component[] components = ((Component)current).GetComponents<Component>(); Component[] array = components; foreach (Component val in array) { if ((Object)(object)val == (Object)null) { continue; } ComponentData componentData = new ComponentData { type = ((object)val).GetType().Name }; if (val is ItemDrop) { FieldInfo[] fields = ((object)val).GetType().GetFields(BindingFlags.Instance | BindingFlags.Public); FieldInfo[] array2 = fields; foreach (FieldInfo fieldInfo in array2) { try { object value = fieldInfo.GetValue(val); if (value != null && !(value is GameObject) && !(value is Component)) { componentData.fields[fieldInfo.Name] = value.ToString(); } } catch (Exception ex) { LogSystem.Error("Error dumping prefab hierarchy: " + ex.Message); } } } prefabNode.components.Add(componentData); } for (int k = 0; k < current.childCount; k++) { prefabNode.children.Add(BuildPrefabNodeElement(current.GetChild(k))); } return prefabNode; } private static void ExportPrefabToObj(GameObject prefab, string outputPath) { //IL_00ee: 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_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_0112: 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_0041: 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_008d: Expected O, but got Unknown //IL_0098: 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_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_00b7: 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_0196: Unknown result type (might be due to invalid IL or missing references) //IL_019b: 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_01b1: Unknown result type (might be due to invalid IL or missing references) if (File.Exists(outputPath)) { return; } try { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine("# Valheim DBDumper - 3D Mesh of Item: " + ((Object)prefab).name); int vOffset = 1; int nOffset = 1; int uvOffset = 1; Matrix4x4 worldToLocalMatrix = prefab.transform.worldToLocalMatrix; SkinnedMeshRenderer[] componentsInChildren = prefab.GetComponentsInChildren<SkinnedMeshRenderer>(true); SkinnedMeshRenderer[] array = componentsInChildren; foreach (SkinnedMeshRenderer val in array) { if ((Object)(object)val == (Object)null || (Object)(object)val.sharedMesh == (Object)null) { continue; } Mesh val2 = new Mesh(); try { val.BakeMesh(val2); Matrix4x4 localToRoot = worldToLocalMatrix * ((Component)val).transform.localToWorldMatrix; ProcessMeshAsset(val2, ((Object)val).name, stringBuilder, localToRoot, ref vOffset, ref nOffset, ref uvOffset); } catch (Exception ex) { LogSystem.Warn("Error processing mesh " + ((Object)val).name + ": " + ex.Message); Matrix4x4 localToRoot2 = worldToLocalMatrix * ((Component)val).transform.localToWorldMatrix; ProcessMeshAsset(val.sharedMesh, ((Object)val).name, stringBuilder, localToRoot2, ref vOffset, ref nOffset, ref uvOffset); } finally { if ((Object)(object)val2 != (Object)null) { Object.Destroy((Object)(object)val2); } } } MeshFilter[] componentsInChildren2 = prefab.GetComponentsInChildren<MeshFilter>(true); MeshFilter[] array2 = componentsInChildren2; foreach (MeshFilter val3 in array2) { if (!((Object)(object)val3 == (Object)null) && !((Object)(object)val3.sharedMesh == (Object)null)) { Matrix4x4 localToRoot3 = worldToLocalMatrix * ((Component)val3).transform.localToWorldMatrix; ProcessMeshAsset(val3.sharedMesh, ((Object)val3).name, stringBuilder, localToRoot3, ref vOffset, ref nOffset, ref uvOffset); } } if (vOffset > 1) { File.WriteAllText(outputPath, stringBuilder.ToString()); } } catch (Exception ex2) { LogSystem.Error("Error exporting prefab to OBJ: " + ex2.Message); } } private static void ProcessMeshAsset(Mesh mesh, string name, StringBuilder sb, Matrix4x4 localToRoot, ref int vOffset, ref int nOffset, ref int uvOffset) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: 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_004c: 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_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: 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_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: 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_00f7: 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_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0108: 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_0120: Unknown result type (might be due to invalid IL or missing references) sb.AppendLine("\ng " + name); Vector3[] vertices = mesh.vertices; Vector3[] array = vertices; foreach (Vector3 val in array) { Vector3 val2 = ((Matrix4x4)(ref localToRoot)).MultiplyPoint3x4(val); sb.AppendLine($"v {val2.x} {val2.y} {val2.z}"); } Vector2[] uv = mesh.uv; Vector2[] array2 = uv; foreach (Vector2 val3 in array2) { sb.AppendLine($"vt {val3.x} {val3.y}"); } Vector3[] normals = mesh.normals; Vector3[] array3 = normals; foreach (Vector3 val4 in array3) { Vector3 val5 = ((Matrix4x4)(ref localToRoot)).MultiplyVector(val4); Vector3 normalized = ((Vector3)(ref val5)).normalized; sb.AppendLine($"vn {normalized.x} {normalized.y} {normalized.z}"); } bool flag = uv.Length != 0; bool flag2 = normals.Length != 0; for (int l = 0; l < mesh.subMeshCount; l++) { int[] triangles = mesh.GetTriangles(l); for (int m = 0; m < triangles.Length; m += 3) { int num = triangles[m] + vOffset; int num2 = triangles[m + 1] + vOffset; int num3 = triangles[m + 2] + vOffset; int num4 = triangles[m] + uvOffset; int num5 = triangles[m + 1] + uvOffset; int num6 = triangles[m + 2] + uvOffset; int num7 = triangles[m] + nOffset; int num8 = triangles[m + 1] + nOffset; int num9 = triangles[m + 2] + nOffset; if (flag && flag2) { sb.AppendLine($"f {num3}/{num6}/{num9} {num2}/{num5}/{num8} {num}/{num4}/{num7}"); } else if (flag) { sb.AppendLine($"f {num3}/{num6} {num2}/{num5} {num}/{num4}"); } else if (flag2) { sb.AppendLine($"f {num3}//{num9} {num2}//{num8} {num}//{num7}"); } else { sb.AppendLine($"f {num3} {num2} {num}"); } } } vOffset += vertices.Length; uvOffset += uv.Length; nOffset += normals.Length; } private static void ExportItemSkinTexture(GameObject prefab, string texturesFolder, string prefabName) { string text = Path.Combine(texturesFolder, prefabName + ".png"); if (File.Exists(text)) { return; } Renderer[] componentsInChildren = prefab.GetComponentsInChildren<Renderer>(true); Renderer[] array = componentsInChildren; foreach (Renderer val in array) { if (!((Object)(object)val == (Object)null) && !((Object)(object)val.material == (Object)null)) { Texture val2 = val.material.mainTexture; if ((Object)(object)val2 == (Object)null && val.material.HasProperty("_MainTex")) { val2 = val.material.GetTexture("_MainTex"); } if ((Object)(object)val2 != (Object)null && val2.width > 32 && val2.height > 32) { SaveRuntimeTextureAsPNG(val2, text); break; } } } } private static void SaveRuntimeTextureAsPNG(Texture srcTexture, string outputPath) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown //IL_004b: Unknown result type (might be due to invalid IL or missing references) try { int width = srcTexture.width; int height = srcTexture.height; RenderTexture temporary = RenderTexture.GetTemporary(width, height, 0, (RenderTextureFormat)7, (RenderTextureReadWrite)1); Graphics.Blit(srcTexture, temporary); RenderTexture active = RenderTexture.active; RenderTexture.active = temporary; Texture2D val = new Texture2D(width, height, (TextureFormat)4, false); val.ReadPixels(new Rect(0f, 0f, (float)width, (float)height), 0, 0); val.Apply(); RenderTexture.active = active; RenderTexture.ReleaseTemporary(temporary); byte[] bytes = ImageConversion.EncodeToPNG(val); File.WriteAllBytes(outputPath, bytes); Object.Destroy((Object)(object)val); } catch (Exception ex) { LogSystem.Error("Failed to export " + outputPath + ": " + ex.Message); } } private static string TranslateToken(string token) { if (string.IsNullOrEmpty(token)) { return ""; } if (!token.StartsWith("$")) { return token; } try { Type type = typeof(Terminal).Assembly.GetType("Localization") ?? Type.GetType("Valheim.Localization, assembly_valheim"); if (type == null) { return token; } object obj = type.GetProperty("instance", BindingFlags.Static | BindingFlags.Public)?.GetValue(null); if (obj == null) { return token; } return (type.GetMethod("Localize", new Type[1] { typeof(string) })?.Invoke(obj, new object[1] { token }) as string) ?? token; } catch (Exception ex) { LogSystem.Error("Error translating token: " + ex.Message); return token; } } private static void SaveCroppedSpriteAsPNG(Sprite sprite, string outputPath) { //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_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Expected O, but got Unknown //IL_0094: Unknown result type (might be due to invalid IL or missing references) if (File.Exists(outputPath)) { return; } try { Texture2D texture = sprite.texture; if (!((Object)(object)texture == (Object)null)) { Rect textureRect = sprite.textureRect; int num = (int)((Rect)(ref textureRect)).width; int num2 = (int)((Rect)(ref textureRect)).height; RenderTexture temporary = RenderTexture.GetTemporary(((Texture)texture).width, ((Texture)texture).height, 0, (RenderTextureFormat)7, (RenderTextureReadWrite)1); Graphics.Blit((Texture)(object)texture, temporary); RenderTexture active = RenderTexture.active; RenderTexture.active = temporary; Texture2D val = new Texture2D(num, num2, (TextureFormat)4, false); val.ReadPixels(new Rect(((Rect)(ref textureRect)).x, ((Rect)(ref textureRect)).y, (float)num, (float)num2), 0, 0); val.Apply(); RenderTexture.active = active; RenderTexture.ReleaseTemporary(temporary); byte[] bytes = ImageConversion.EncodeToPNG(val); File.WriteAllBytes(outputPath, bytes); Object.Destroy((Object)(object)val); } } catch (Exception ex) { LogSystem.Error("Failed to export " + outputPath + ": " + ex.Message); } } } public class PickableDataDump { public string prefab_name { get; set; } public string pickable_name { get; set; } public string pickable_rawName { get; set; } public string drop_item_prefab { get; set; } public int min_amount { get; set; } public int max_amount { get; set; } public int respawn_minutes { get; set; } } public static class PickablesExporter { [CompilerGenerated] private sealed class <ExportPickablesCoroutine>d__0 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public string baseFolder; public ConsoleEventArgs args; public bool exportJson; public bool exportIcons; public bool exportPrefab; public bool exportModel3d; public Action onFinished; private string <pickablesFolder>5__1; private string <iconsFolder>5__2; private string <prefabsFolder>5__3; private string <modelsFolder>5__4; private string <texturesFolder>5__5; private List<GameObject> <allPrefabs>5__6; private List<PickableDataDump> <exportedPickables>5__7; private int <operationsThisFrame>5__8; private int <i>5__9; private GameObject <prefab>5__10; private Pickable <pickable>5__11; private string <prefabName>5__12; private GameObject <dropItemObj>5__13; private string <dropPrefabName>5__14; private ItemDrop <itemDrop>5__15; private string <rawName>5__16; private PickableDataDump <data>5__17; private string <targetFile>5__18; private string <targetObjPath>5__19; private string <jsonOutput>5__20; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <ExportPickablesCoroutine>d__0(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <pickablesFolder>5__1 = null; <iconsFolder>5__2 = null; <prefabsFolder>5__3 = null; <modelsFolder>5__4 = null; <texturesFolder>5__5 = null; <allPrefabs>5__6 = null; <exportedPickables>5__7 = null; <prefab>5__10 = null; <pickable>5__11 = null; <prefabName>5__12 = null; <dropItemObj>5__13 = null; <dropPrefabName>5__14 = null; <itemDrop>5__15 = null; <rawName>5__16 = null; <data>5__17 = null; <targetFile>5__18 = null; <targetObjPath>5__19 = null; <jsonOutput>5__20 = null; <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <pickablesFolder>5__1 = Path.Combine(baseFolder, "data", "pickables"); <iconsFolder>5__2 = Path.Combine(baseFolder, "icons"); <prefabsFolder>5__3 = Path.Combine(baseFolder, "prefabs", "pickables"); <modelsFolder>5__4 = Path.Combine(baseFolder, "models", "pickables"); <texturesFolder>5__5 = Path.Combine(baseFolder, "textures", "pickables"); if (exportJson) { Directory.CreateDirectory(<pickablesFolder>5__1); } if (exportIcons) { Directory.CreateDirectory(<iconsFolder>5__2); } if (exportPrefab) { Directory.CreateDirectory(<prefabsFolder>5__3); } if (exportModel3d) { Directory.CreateDirectory(<modelsFolder>5__4); Directory.CreateDirectory(<texturesFolder>5__5); } <allPrefabs>5__6 = ZNetScene.instance.m_prefabs; <exportedPickables>5__7 = new List<PickableDataDump>(); args.Context.AddString($"<color=yellow>[Valheim DBDumper] Scanning {<allPrefabs>5__6.Count} game prefabs for pickables...</color>"); LogSystem.Info($"Scanning {<allPrefabs>5__6.Count} game prefabs for pickables..."); <>2__current = null; <>1__state = 1; return true; case 1: <>1__state = -1; <operationsThisFrame>5__8 = 0; <i>5__9 = 0; goto IL_05ad; case 2: { <>1__state = -1; goto IL_0577; } IL_05ad: if (<i>5__9 < <allPrefabs>5__6.Count) { <prefab>5__10 = <allPrefabs>5__6[<i>5__9]; if (!((Object)(object)<prefab>5__10 == (Object)null)) { <pickable>5__11 = <prefab>5__10.GetComponent<Pickable>(); if (!((Object)(object)<pickable>5__11 == (Object)null)) { <prefabName>5__12 = ((Object)<prefab>5__10).name; <dropItemObj>5__13 = <pickable>5__11.m_itemPrefab; <dropPrefabName>5__14 = (((Object)(object)<dropItemObj>5__13 != (Object)null) ? ((Object)<dropItemObj>5__13).name : "None"); if (exportIcons && (Object)(object)<dropItemObj>5__13 != (Object)null) { Directory.CreateDirectory(Path.Combine(<iconsFolder>5__2, "Pickables")); <itemDrop>5__15 = <dropItemObj>5__13.GetComponent<ItemDrop>(); if ((Object)(object)<itemDrop>5__15 != (Object)null) { ItemData itemData = <itemDrop>5__15.m_itemData; if (itemData != null && itemData.m_shared?.m_icons?.Length > 0) { SaveCroppedSpriteAsPNG(<itemDrop>5__15.m_itemData.m_shared.m_icons[0], Path.Combine(<iconsFolder>5__2, "Pickables", <prefabName>5__12 + ".png")); <operationsThisFrame>5__8++; } } <itemDrop>5__15 = null; } if (exportJson) { <rawName>5__16 = (string.IsNullOrEmpty(((Object)<pickable>5__11).name) ? <prefabName>5__12 : ((Object)<pickable>5__11).name); <data>5__17 = new PickableDataDump { prefab_name = <prefabName>5__12, pickable_name = TranslateToken(<rawName>5__16), pickable_rawName = <rawName>5__16, drop_item_prefab = <dropPrefabName>5__14, min_amount = <pickable>5__11.m_amount, max_amount = <pickable>5__11.m_amount, respawn_minutes = (int)<pickable>5__11.m_respawnTimeMinutes }; <exportedPickables>5__7.Add(<data>5__17); <rawName>5__16 = null; <data>5__17 = null; } if (exportPrefab) { <targetFile>5__18 = Path.Combine(<prefabsFolder>5__3, <prefabName>5__12 + ".json"); DumpPrefabHierarchyToJson(<prefab>5__10, <targetFile>5__18); <operationsThisFrame>5__8++; <targetFile>5__18 = null; } if (exportModel3d) { <targetObjPath>5__19 = Path.Combine(<modelsFolder>5__4, <prefabName>5__12 + ".obj"); ExportPrefabToObj(<prefab>5__10, <targetObjPath>5__19); ExportPickableSkinTexture(<prefab>5__10, <texturesFolder>5__5, <prefabName>5__12); <operationsThisFrame>5__8++; <targetObjPath>5__19 = null; } if (<exportedPickables>5__7.Count % 15 == 0) { args.Context.AddString($"<color=lightblue>[Valheim DBDumper] Processed {<exportedPickables>5__7.Count} unique pickables...</color>"); } if (<operationsThisFrame>5__8 >= 30) { <operationsThisFrame>5__8 = 0; <>2__current = null; <>1__state = 2; return true; } goto IL_0577; } } goto IL_059b; } if (exportJson && <exportedPickables>5__7.Count > 0) { <jsonOutput>5__20 = JsonConvert.SerializeObject((object)<exportedPickables>5__7, (Formatting)1); File.WriteAllText(Path.Combine(<pickablesFolder>5__1, "pickables.json"), <jsonOutput>5__20); <jsonOutput>5__20 = null; } args.Context.AddString($"<color=green>[Valheim DBDumper] Pickables module finished! Saved {<exportedPickables>5__7.Count} environment assets and geometries.</color>"); LogSystem.Success($"Pickables module finished! Saved {<exportedPickables>5__7.Count} environment assets and geometries."); onFinished?.Invoke(); return false; IL_0577: <prefab>5__10 = null; <pickable>5__11 = null; <prefabName>5__12 = null; <dropItemObj>5__13 = null; <dropPrefabName>5__14 = null; goto IL_059b; IL_059b: <i>5__9++; goto IL_05ad; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [IteratorStateMachine(typeof(<ExportPickablesCoroutine>d__0))] public static IEnumerator ExportPickablesCoroutine(string baseFolder, ConsoleEventArgs args, bool exportJson, bool exportIcons, bool exportPrefab, bool exportModel3d, Action onFinished) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <ExportPickablesCoroutine>d__0(0) { baseFolder = baseFolder, args = args, exportJson = exportJson, exportIcons = exportIcons, exportPrefab = exportPrefab, exportModel3d = exportModel3d, onFinished = onFinished }; } private static void DumpPrefabHierarchyToJson(GameObject prefab, string outputPath) { try { PrefabNode prefabNode = BuildPrefabNodeElement(prefab.transform); string contents = JsonConvert.SerializeObject((object)prefabNode, (Formatting)1); File.WriteAllText(outputPath, contents); } catch (Exception ex) { LogSystem.Error("Error dumping prefab hierarchy: " + ex.Message); } } private static PrefabNode BuildPrefabNodeElement(Transform current) { PrefabNode prefabNode = new PrefabNode { object_name = ((Object)current).name, is_active = ((Component)current).gameObject.activeSelf, layer = LayerMask.LayerToName(((Component)current).gameObject.layer), tag = ((Component)current).gameObject.tag }; Component[] components = ((Component)current).GetComponents<Component>(); Component[] array = components; foreach (Component val in array) { if ((Object)(object)val == (Object)null) { continue; } ComponentData componentData = new ComponentData { type = ((object)val).GetType().Name }; if (val is Pickable) { FieldInfo[] fields = ((object)val).GetType().GetFields(BindingFlags.Instance | BindingFlags.Public); FieldInfo[] array2 = fields; foreach (FieldInfo fieldInfo in array2) { try { object value = fieldInfo.GetValue(val); if (value != null && !(value is GameObject) && !(value is Component)) { componentData.fields[fieldInfo.Name] = value.ToString(); } } catch (Exception ex) { LogSystem.Error("Error getting field value: " + ex.Message); } } } prefabNode.components.Add(componentData); } for (int k = 0; k < current.childCount; k++) { prefabNode.children.Add(BuildPrefabNodeElement(current.GetChild(k))); } return prefabNode; } private static void ExportPrefabToObj(GameObject prefab, string outputPath) { //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: 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_0106: 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_0041: 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_008d: Expected O, but got Unknown //IL_0098: 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_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_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Unknown result type (might be due to invalid IL or missing references) //IL_018f: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_01a5: Unknown result type (might be due to invalid IL or missing references) if (File.Exists(outputPath)) { return; } try { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine("# Valheim DBDumper - 3D Mesh of Pickable Resource: " + ((Object)prefab).name); int vOffset = 1; int nOffset = 1; int uvOffset = 1; Matrix4x4 worldToLocalMatrix = prefab.transform.worldToLocalMatrix; SkinnedMeshRenderer[] componentsInChildren = prefab.GetComponentsInChildren<SkinnedMeshRenderer>(true); SkinnedMeshRenderer[] array = componentsInChildren; foreach (SkinnedMeshRenderer val in array) { if ((Object)(object)val == (Object)null || (Object)(object)val.sharedMesh == (Object)null) { continue; } Mesh val2 = new Mesh(); try { val.BakeMesh(val2); Matrix4x4 localToRoot = worldToLocalMatrix * ((Component)val).transform.localToWorldMatrix; ProcessMeshAsset(val2, ((Object)val).name, stringBuilder, localToRoot, ref vOffset, ref nOffset, ref uvOffset); } catch (Exception ex) { LogSystem.Warn("Error baking mesh: " + ex.Message); Matrix4x4 localToRoot2 = worldToLocalMatrix * ((Component)val).transform.localToWorldMatrix; ProcessMeshAsset(val.sharedMesh, ((Object)val).name, stringBuilder, localToRoot2, ref vOffset, ref nOffset, ref uvOffset); } finally { if ((Object)(object)val2 != (Object)null) { Object.Destroy((Object)(object)val2); } } } MeshFilter[] componentsInChildren2 = prefab.GetComponentsInChildren<MeshFilter>(true); MeshFilter[] array2 = componentsInChildren2; foreach (MeshFilter val3 in array2) { if (!((Object)(object)val3 == (Object)null) && !((Object)(object)val3.sharedMesh == (Object)null)) { Matrix4x4 localToRoot3 = worldToLocalMatrix * ((Component)val3).transform.localToWorldMatrix; ProcessMeshAsset(val3.sharedMesh, ((Object)val3).name, stringBuilder, localToRoot3, ref vOffset, ref nOffset, ref uvOffset); } } if (vOffset > 1) { File.WriteAllText(outputPath, stringBuilder.ToString()); } } catch (Exception ex2) { LogSystem.Error("Error exporting prefab to OBJ: " + ex2.Message); } } private static void ProcessMeshAsset(Mesh mesh, string name, StringBuilder sb, Matrix4x4 localToRoot, ref int vOffset, ref int nOffset, ref int uvOffset) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: 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_004c: 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_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: 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_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: 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_00f7: 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_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0108: 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_0120: Unknown result type (might be due to invalid IL or missing references) sb.AppendLine("\ng " + name); Vector3[] vertices = mesh.vertices; Vector3[] array = vertices; foreach (Vector3 val in array) { Vector3 val2 = ((Matrix4x4)(ref localToRoot)).MultiplyPoint3x4(val); sb.AppendLine($"v {val2.x} {val2.y} {val2.z}"); } Vector2[] uv = mesh.uv; Vector2[] array2 = uv; foreach (Vector2 val3 in array2) { sb.AppendLine($"vt {val3.x} {val3.y}"); } Vector3[] normals = mesh.normals; Vector3[] array3 = normals; foreach (Vector3 val4 in array3) { Vector3 val5 = ((Matrix4x4)(ref localToRoot)).MultiplyVector(val4); Vector3 normalized = ((Vector3)(ref val5)).normalized; sb.AppendLine($"vn {normalized.x} {normalized.y} {normalized.z}"); } bool flag = uv.Length != 0; bool flag2 = normals.Length != 0; for (int l = 0; l < mesh.subMeshCount; l++) { int[] triangles = mesh.GetTriangles(l); for (int m = 0; m < triangles.Length; m += 3) { int num = triangles[m] + vOffset; int num2 = triangles[m + 1] + vOffset; int num3 = triangles[m + 2] + vOffset; int num4 = triangles[m] + uvOffset; int num5 = triangles[m + 1] + uvOffset; int num6 = triangles[m + 2] + uvOffset; int num7 = triangles[m] + nOffset; int num8 = triangles[m + 1] + nOffset; int num9 = triangles[m + 2] + nOffset; if (flag && flag2) { sb.AppendLine($"f {num3}/{num6}/{num9} {num2}/{num5}/{num8} {num}/{num4}/{num7}"); } else if (flag) { sb.AppendLine($"f {num3}/{num6} {num2}/{num5} {num}/{num4}"); } else if (flag2) { sb.AppendLine($"f {num3}//{num9} {num2}//{num8} {num}//{num7}"); } else { sb.AppendLine($"f {num3} {num2} {num}"); } } } vOffset += vertices.Length; uvOffset += uv.Length; nOffset += normals.Length; } private static void ExportPickableSkinTexture(GameObject prefab, string texturesFolder, string prefabName) { string text = Path.Combine(texturesFolder, prefabName + ".png"); if (File.Exists(text)) { return; } Renderer[] componentsInChildren = prefab.GetComponentsInChildren<Renderer>(true); Renderer[] array = componentsInChildren; foreach (Renderer val in array) { if (!((Object)(object)val == (Object)null) && !((Object)(object)val.material == (Object)null)) { Texture val2 = val.material.mainTexture; if ((Object)(object)val2 == (Object)null && val.material.HasProperty("_MainTex")) { val2 = val.material.GetTexture("_MainTex"); } if ((Object)(object)val2 != (Object)null && val2.width > 32 && val2.height > 32) { SaveRuntimeTextureAsPNG(val2, text); break; } } } } private static void SaveRuntimeTextureAsPNG(Texture srcTexture, string outputPath) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown //IL_004b: Unknown result type (might be due to invalid IL or missing references) try { int width = srcTexture.width; int height = srcTexture.height; RenderTexture temporary = RenderTexture.GetTemporary(width, height, 0, (RenderTextureFormat)7, (RenderTextureReadWrite)1); Graphics.Blit(srcTexture, temporary); RenderTexture active = RenderTexture.active; RenderTexture.active = temporary; Texture2D val = new Texture2D(width, height, (TextureFormat)4, false); val.ReadPixels(new Rect(0f, 0f, (float)width, (float)height), 0, 0); val.Apply(); RenderTexture.active = active; RenderTexture.ReleaseTemporary(temporary); byte[] bytes = ImageConversion.EncodeToPNG(val); File.WriteAllBytes(outputPath, bytes); Object.Destroy((Object)(object)val); } catch (Exception ex) { LogSystem.Error("Error saving runtime texture: " + ex.Message); } } private static string TranslateToken(string token) { if (string.IsNullOrEmpty(token)) { return ""; } if (!token.StartsWith("$")) { return token; } try { Type type = typeof(Terminal).Assembly.GetType("Localization") ?? Type.GetType("Valheim.Localization, assembly_valheim"); if (type == null) { return token; } object obj = type.GetProperty("instance", BindingFlags.Static | BindingFlags.Public)?.GetValue(null); if (obj == null) { return token; } return (type.GetMethod("Localize", new Type[1] { typeof(string) })?.Invoke(obj, new object[1] { token }) as string) ?? token; } catch (Exception ex) { LogSystem.Error("Error translating token: " + ex.Message); return token; } } private static void SaveCroppedSpriteAsPNG(Sprite sprite, string outputPath) { //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_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Expected O, but got Unknown //IL_0094: Unknown result type (might be due to invalid IL or missing references) if (File.Exists(outputPath)) { return; } try { Texture2D texture = sprite.texture; if (!((Object)(object)texture == (Object)null)) { Rect textureRect = sprite.textureRect; int num = (int)((Rect)(ref textureRect)).width; int num2 = (int)((Rect)(ref textureRect)).height; RenderTexture temporary = RenderTexture.GetTemporary(((Texture)texture).width, ((Texture)texture).height, 0, (RenderTextureFormat)7, (RenderTextureReadWrite)1); Graphics.Blit((Texture)(object)texture, temporary); RenderTexture active = RenderTexture.active; RenderTexture.active = temporary; Texture2D val = new Texture2D(num, num2, (TextureFormat)4, false); val.ReadPixels(new Rect(((Rect)(ref textureRect)).x, ((Rect)(ref textureRect)).y, (float)num, (float)num2), 0, 0); val.Apply(); RenderTexture.active = active; RenderTexture.ReleaseTemporary(temporary); byte[] bytes = ImageConversion.EncodeToPNG(val); File.WriteAllBytes(outputPath, bytes); Object.Destroy((Object)(object)val); } } catch (Exception ex) { LogSystem.Error("Error saving cropped sprite: " + ex.Message); } } } public class PieceDataDump { public string prefab_name { get; set; } public string piece_name { get; set; } public string piece_rawName { get; set; } public string description { get; set; } public string category { get; set; } public string primary_tool { get; set; } public string required_station { get; set; } public List<PieceRequirementData> resources { get; set; } = new List<PieceRequirementData>(); } public class PieceRequirementData { public string item_prefab { get; set; } public int amount { get; set; } public bool recover { get; set; } } public static class PiecesExporter { [CompilerGenerated] private sealed class <ExportPiecesCoroutine>d__0 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public string baseFolder; public ConsoleEventArgs args; public bool exportJson; public bool exportIcons; public Action onFinished; private string <piecesFolder>5__1; private string <iconsFolder>5__2; private List<GameObject> <itemPrefabs>5__3; private List<PieceDataDump> <exportedPieces>5__4; private HashSet<string> <processedPrefabs>5__5; private int <operationsThisFrame>5__6; private List<GameObject>.Enumerator <>s__7; private GameObject <itemObj>5__8; private ItemDrop <itemDrop>5__9; private PieceTable <pieceTable>5__10; private string <toolName>5__11; private List<GameObject>.Enumerator <>s__12; private GameObject <pieceObj>5__13; private string <prefabName>5__14; private Piece <piece>5__15; private string <stationName>5__16; private PieceDataDump <data>5__17; private Requirement[] <>s__18; private int <>s__19; private Requirement <req>5__20; private string <jsonOutput>5__21; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <ExportPiecesCoroutine>d__0(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if ((uint)(num - -4) <= 1u || num == 2) { try { if (num == -4 || num == 2) { try { } finally { <>m__Finally2(); } } } finally { <>m__Finally1(); } } <piecesFolder>5__1 = null; <iconsFolder>5__2 = null; <itemPrefabs>5__3 = null; <exportedPieces>5__4 = null; <processedPrefabs>5__5 = null; <>s__7 = default(List<GameObject>.Enumerator); <itemObj>5__8 = null; <itemDrop>5__9 = null; <pieceTable>5__10 = null; <toolName>5__11 = null; <>s__12 = default(List<GameObject>.Enumerator); <pieceObj>5__13 = null; <prefabName>5__14 = null; <piece>5__15 = null; <stationName>5__16 = null; <data>5__17 = null; <>s__18 = null; <req>5__20 = null; <jsonOutput>5__21 = null; <>1__state = -2; } private bool MoveNext() { try { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <piecesFolder>5__1 = Path.Combine(baseFolder, "data", "pieces"); <iconsFolder>5__2 = Path.Combine(baseFolder, "icons"); if (exportJson) { Directory.CreateDirectory(<piecesFolder>5__1); } if (exportIcons) { Directory.CreateDirectory(<iconsFolder>5__2); } <itemPrefabs>5__3 = ObjectDB.instance.m_items; <exportedPieces>5__4 = new List<PieceDataDump>(); <processedPrefabs>5__5 = new HashSet<string>(); args.Context.AddString("<color=yellow>[Valheim DBDumper] Scanning tools for building pieces...</color>"); LogSystem.Info("Scanning tools for building pieces..."); <>2__current = null; <>1__state = 1; return true; case 1: <>1__state = -1; <operationsThisFrame>5__6 = 0; <>s__7 = <itemPrefabs>5__3.GetEnumerator(); <>1__state = -3; goto IL_05c2; case 2: { <>1__state = -4; goto IL_056c; } IL_05c2: while (true) { if (<>s__7.MoveNext()) { <itemObj>5__8 = <>s__7.Current; if ((Object)(object)<itemObj>5__8 == (Object)null) { continue; } <itemDrop>5__9 = <itemObj>5__8.GetComponent<ItemDrop>(); if (!((Object)(object)<itemDrop>5__9 == (Object)null) && <itemDrop>5__9.m_itemData != null) { <pieceTable>5__10 = <itemDrop>5__9.m_itemData.m_shared.m_buildPieces; if (!((Object)(object)<pieceTable>5__10 == (Object)null) && <pieceTable>5__10.m_pieces != null) { break; } } continue; } <>m__Finally1(); <>s__7 = default(List<GameObject>.Enumerator); if (exportJson && <exportedPieces>5__4.Count > 0) { <jsonOutput>5__21 = JsonConvert.SerializeObject((object)<exportedPieces>5__4, (Formatting)1); File.WriteAllText(Path.Combine(<piecesFolder>5__1, "pieces.json"), <jsonOutput>5__21); <jsonOutput>5__21 = null; } args.Context.AddString($"<color=green>[Valheim DBDumper] Pieces module finished! Saved {<exportedPieces>5__4.Count} unique structures.</color>"); LogSystem.Success($"Pieces module finished! Saved {<exportedPieces>5__4.Count} unique structures."); onFinished?.Invoke(); return false; } Directory.CreateDirectory(Path.Combine(<iconsFolder>5__2, "Pieces")); <toolName>5__11 = ((Object)<itemObj>5__8).name; <>s__12 = <pieceTable>5__10.m_pieces.GetEnumerator(); <>1__state = -4; goto IL_0582; IL_056c: <prefabName>5__14 = null; <piece>5__15 = null; <pieceObj>5__13 = null; goto IL_0582; IL_0582: while (<>s__12.MoveNext()) { <pieceObj>5__13 = <>s__12.Current; if ((Object)(object)<pieceObj>5__13 == (Object)null) { continue; } <prefabName>5__14 = ((Object)<pieceObj>5__13).name; if (<processedPrefabs>5__5.Contains(<prefabName>5__14)) { continue; } <piece>5__15 = <pieceObj>5__13.GetComponent<Piece>(); if ((Object)(object)<piece>5__15 == (Object)null) { continue; } goto IL_028e; } <>m__Finally2(); <>s__12 = default(List<GameObject>.Enumerator); <itemDrop>5__9 = null; <pieceTable>5__10 = null; <toolName>5__11 = null; <itemObj>5__8 = null; goto IL_05c2; IL_028e: if (exportIcons && (Object)(object)<piece>5__15.m_icon != (Object)null) { SaveCroppedSpriteAsPNG(<piece>5__15.m_icon, Path.Combine(<iconsFolder>5__2, "Pieces", <prefabName>5__14 + ".png")); <operationsThisFrame>5__6++; } if (exportJson) { <stationName>5__16 = (((Object)(object)<piece>5__15.m_craftingStation != (Object)null) ? <piece>5__15.m_craftingStation.m_name : "None"); <data>5__17 = new PieceDataDump { prefab_name = <prefabName>5__14, piece_name = TranslateToken(<piece>5__15.m_name), piece_rawName = <piece>5__15.m_name, description = TranslateToken(<piece>5__15.m_description), category = ((object)(PieceCategory)(ref <piece>5__15.m_category)).ToString(), primary_tool = <toolName>5__11, required_station = <stationName>5__16 }; if (<piece>5__15.m_resources != null) { <>s__18 = <piece>5__15.m_resources; for (<>s__19 = 0; <>s__19 < <>s__18.Length; <>s__19++) { <req>5__20 = <>s__18[<>s__19]; if (<req>5__20 != null && !((Object)(object)<req>5__20.m_resItem == (Object)null)) { <data>5__17.resources.Add(new PieceRequirementData { item_prefab = ((Object)((Component)<req>5__20.m_resItem).gameObject).name, amount = <req>5__20.m_amount, recover = <req>5__20.m_recover }); <req>5__20 = null; } } <>s__18 = null; } <exportedPieces>5__4.Add(<data>5__17); <stationName>5__16 = null; <data>5__17 = null; } <processedPrefabs>5__5.Add(<prefabName>5__14); if (<processedPrefabs>5__5.Count % 50 == 0) { args.Context.AddString($"<color=lightblue>[Valheim DBDumper] Processed {<processedPrefabs>5__5.Count} unique building pieces...</color>"); } if (<operationsThisFrame>5__6 >= 25) { <operationsThisFrame>5__6 = 0; <>2__current = null; <>1__state = 2; return true; } goto IL_056c; } } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; ((IDisposable)<>s__7).Dispose(); } private void <>m__Finally2() { <>1__state = -3; ((IDisposable)<>s__12).Dispose(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [IteratorStateMachine(typeof(<ExportPiecesCoroutine>d__0))] public static IEnumerator ExportPiecesCoroutine(string baseFolder, ConsoleEventArgs args, bool exportJson, bool exportIcons, Action onFinished) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <ExportPiecesCoroutine>d__0(0) { baseFolder = baseFolder, args = args, exportJson = exportJson, exportIcons = exportIcons, onFinished = onFinished }; } private static string TranslateToken(string token) { if (string.IsNullOrEmpty(token)) { return ""; } if (!token.StartsWith("$")) { return token; } try { Type type = typeof(Terminal).Assembly.GetType("Localization") ?? Type.GetType("Valheim.Localization, assembly_valheim"); if (type == null) { return token; } object obj = type.GetProperty("instance", BindingFlags.Static | BindingFlags.Public)?.GetValue(null); if (obj == null) { return token; } return (type.GetMethod("Localize", new Type[1] { typeof(string) })?.Invoke(obj, new object[1] { token }) as string) ?? token; } catch (Exception ex) { LogSystem.Error("Error translating token: " + ex.Message); return token; } } private static void SaveCroppedSpriteAsPNG(Sprite sprite, string outputPath) { //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_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Expected O, but got Unknown //IL_0094: Unknown result type (might be due to invalid IL or missing references) if (File.Exists(outputPath)) { return; } try { Texture2D texture = sprite.texture; if (!((Object)(object)texture == (Object)null)) { Rect textureRect = sprite.textureRect; int num = (int)((Rect)(ref textureRect)).width; int num2 = (int)((Rect)(ref textureRect)).height; RenderTexture temporary = RenderTexture.GetTemporary(((Texture)texture).width, ((Texture)texture).height, 0, (RenderTextureFormat)7, (RenderTextureReadWrite)1); Graphics.Blit((Texture)(object)texture, temporary); RenderTexture active = RenderTexture.active; RenderTexture.active = temporary; Texture2D val = new Texture2D(num, num2, (TextureFormat)4, false); val.ReadPixels(new Rect(((Rect)(ref textureRect)).x, ((Rect)(ref textureRect)).y, (float)num, (float)num2), 0, 0); val.Apply(); RenderTexture.active = active; RenderTexture.ReleaseTemporary(temporary); byte[] bytes = ImageConversion.EncodeToPNG(val); File.WriteAllBytes(outputPath, bytes); Object.Destroy((Object)(object)val); } } catch (Exception ex) { LogSystem.Error("Error saving cropped sprite as PNG: " + ex.Message); } } } public class RecipeData { public string prefab_name { get; set; } public string item_name { get; set; } public string item_rawName { get; set; } public string crafting_station { get; set; } public int min_station_level { get; set; } public int amount { get; set; } public List<RequirementData> requirements { get; set; } = new List<RequirementData>(); } public class RequirementData { public string item_prefab { get; set; } public int amount { get; set; } public int amount_per_level { get; set; } } public static class RecipeExporter { [CompilerGenerated] private sealed class <ExportRecipesCoroutine>d__0 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public string baseFolder; public ConsoleEventArgs args; public bool exportJson; public bool exportIcons; public Action onFinished; private string <recipesFolder>5__1; private string <iconsFolder>5__2; private List<Recipe> <recipeList>5__3; private List<RecipeData> <exportedRecipes>5__4; private int <operationsThisFrame>5__5; private int <i>5__6; private Recipe <recipe>5__7; private string <prefabName>5__8; private Sprite[] <iconsArray>5__9; private string <itemName>5__10; private string <stationName>5__11; private RecipeData <data>5__12; private Requirement[] <>s__13; private int <>s__14; private Requirement <req>5__15; private string <jsonOutput>5__16; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <ExportRecipesCoroutine>d__0(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <recipesFolder>5__1 = null; <iconsFolder>5__2 = null; <recipeList>5__3 = null; <exportedRecipes>5__4 = null; <recipe>5__7 = null; <prefabName>5__8 = null; <iconsArray>5__9 = null; <itemName>5__10 = null; <stationName>5__11 = null; <data>5__12 = null; <>s__13 = null; <req>5__15 = null; <jsonOutput>5__16 = null; <>1__state = -2; } private bool MoveNext() { int num = <>1__state; if (num != 0) { if (num != 1) { return false; } <>1__state = -1; goto IL_0480; } <>1__state = -1; <recipesFolder>5__1 = Path.Combine(baseFolder, "data", "recipes"); <iconsFolder>5__2 = Path.Combine(baseFolder, "icons"); if (exportJson) { Directory.CreateDirectory(<recipesFolder>5__1); } if (exportIcons) { Directory.CreateDirectory(<iconsFolder>5__2); } <recipeList>5__3 = ObjectDB.instance.m_recipes; <exportedRecipes>5__4 = new List<RecipeData>(); args.Context.AddString($"<color=yellow>[Valheim DBDumper] Processing {<recipeList>5__3.Count} recipes...</color>"); LogSystem.Info($"Processing {<recipeList>5__3.Count} recipes..."); <operationsThisFrame>5__5 = 0; Directory.CreateDirectory(Path.Combine(<iconsFolder>5__2, "Recipes")); <i>5__6 = 0; goto IL_04a1; IL_04a1: if (<i>5__6 < <recipeList>5__3.Count) { <recipe>5__7 = <recipeList>5__3[<i>5__6]; if ((Object)(object)<recipe>5__7 == (Object)null || (Object)(object)<recipe>5__7.m_item == (Object)null) { goto IL_048f; } <prefabName>5__8 = ((Object)((Component)<recipe>5__7.m_item).gameObject).name; if (exportIcons) { <iconsArray>5__9 = <recipe>5__7.m_item.m_itemData.m_shared.m_icons; if (<iconsArray>5__9 != null && <iconsArray>5__9.Length != 0 && (Object)(object)<iconsArray>5__9[0] != (Object)null) { SaveCroppedSpriteAsPNG(<iconsArray>5__9[0], Path.Combine(<iconsFolder>5__2, "Recipes", <prefabName>5__8 + ".png")); <operationsThisFrame>5__5++; } <iconsArray>5__9 = null; } if (exportJson) { <itemName>5__10 = <recipe>5__7.m_item.m_itemData.m_shared.m_name; <stationName>5__11 = (((Object)(object)<recipe>5__7.m_craftingStation != (Object)null) ? <recipe>5__7.m_craftingStation.m_name : "Hand"); <data>5__12 = new RecipeData { prefab_name = <prefabName>5__8, item_name = TranslateToken(<itemName>5__10), item_rawName = <itemName>5__10, crafting_station = <stationName>5__11, min_station_level = <recipe>5__7.m_minStationLevel, amount = <recipe>5__7.m_amount }; if (<recipe>5__7.m_resources != null) { <>s__13 = <recipe>5__7.m_resources; for (<>s__14 = 0; <>s__14 < <>s__13.Length; <>s__14++) { <req>5__15 = <>s__13[<>s__14]; if (<req>5__15 != null && !((Object)(object)<req>5__15.m_resItem == (Object)null)) { <data>5__12.requirements.Add(new RequirementData { item_prefab = ((Object)((Component)<req>5__15.m_resItem).gameObject).name, amount = <req>5__15.m_amount, amount_per_level = <req>5__15.m_amountPerLevel }); <req>5__15 = null; } } <>s__13 = null; } <exportedRecipes>5__4.Add(<data>5__12); <itemName>5__10 = null; <stationName>5__11 = null; <data>5__12 = null; } if (<i>5__6 > 0 && <i>5__6 % 150 == 0) { args.Context.AddString($"<color=lightblue>[Valheim DBDumper] Processed {<i>5__6}/{<recipeList>5__3.Count} recipes...</color>"); } if (<operationsThisFrame>5__5 >= 25) { <operationsThisFrame>5__5 = 0; <>2__current = null; <>1__state = 1; return true; } goto IL_0480; } if (exportJson && <exportedRecipes>5__4.Count > 0) { <jsonOutput>5__16 = JsonConvert.SerializeObject((object)<exportedRecipes>5__4, (Formatting)1); File.WriteAllText(Path.Combine(<recipesFolder>5__1, "recipes.json"), <jsonOutput>5__16); <jsonOutput>5__16 = null; } args.Context.AddString("<color=green>[Valheim DBDumper] Recipe module finished processing successfully!</color>"); LogSystem.Success("Recipe module finished processing successfully!"); onFinished?.Invoke(); return false; IL_0480: <recipe>5__7 = null; <prefabName>5__8 = null; goto IL_048f; IL_048f: <i>5__6++; goto IL_04a1; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [IteratorStateMachine(typeof(<ExportRecipesCoroutine>d__0))] public static IEnumerator ExportRecipesCoroutine(string baseFolder, ConsoleEventArgs args, bool exportJson, bool exportIcons, Action onFinished) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <ExportRecipesCoroutine>d__0(0) { baseFolder = baseFolder, args = args, exportJson = exportJson, exportIcons = exportIcons, onFinished = onFinished }; } private static string TranslateToken(string token) { if (string.IsNullOrEmpty(token)) { return ""; } if (!token.StartsWith("$")) { return token; } try { Type type = typeof(Terminal).Assembly.GetType("Localization") ?? Type.GetType("Valheim.Localization, assembly_valheim"); if (type == null) { return token; } object obj = type.GetProperty("instance", BindingFlags.Static | BindingFlags.Public)?.GetValue(null); if (obj == null) { return token; } return (type.GetMethod("Localize", new Type[1] { typeof(string) })?.Invoke(obj, new object[1] { token }) as string) ?? token; } catch (Exception ex) { LogSystem.Error("Error translating token: " + ex.Message); return token; } } private static void SaveCroppedSpriteAsPNG(Sprite sprite, string outputPath) { //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_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Expected O, but got Unknown //IL_0094: Unknown result type (might be due to invalid IL or missing references) if (File.Exists(outputPath)) { return; } try { Texture2D texture = sprite.texture; if (!((Object)(object)texture == (Object)null)) { Rect textureRect = sprite.textureRect; int num = (int)((Rect)(ref textureRect)).width; int num2 = (int)((Rect)(ref textureRect)).height; RenderTexture temporary = RenderTexture.GetTemporary(((Texture)texture).width, ((Texture)texture).height, 0, (RenderTextureFormat)7, (RenderTextureReadWrite)1); Graphics.Blit((Texture)(object)texture, temporary); RenderTexture active = RenderTexture.active; RenderTexture.active = temporary; Texture2D val = new Texture2D(num, num2, (TextureFormat)4, false); val.ReadPixels(new Rect(((Rect)(ref textureRect)).x, ((Rect)(ref textureRect)).y, (float)num, (float)num2), 0, 0); val.Apply(); RenderTexture.active = active; RenderTexture.ReleaseTemporary(temporary); byte[] bytes = ImageConversion.EncodeToPNG(val); File.WriteAllBytes(outputPath, bytes); Object.Destroy((Object)(object)val); } } catch (Exception ex) { LogSystem.Error("Failed to export " + outputPath + ": " + ex.Message); } } } public class Color { public static readonly string RESET = "\u001b[0m"; public static readonly string BOLD = "\u001b[1m"; public static readonly string DIM = "\u001b[2m"; public static readonly string ITALIC = "\u001b[3m"; public static readonly string UNDERLINE = "\u001b[4m"; public static readonly string BLINK = "\u001b[5m"; public static readonly string REVERSE = "\u001b[7m"; public static readonly string HIDDEN = "\u001b[8m"; public static readonly string STRIKETHROUGH = "\u001b[9m"; public static readonly string BLACK = "\u001b[30m"; public static readonly string RED = "\u001b[31m"; public static readonly string GREEN = "\u001b[32m"; public static readonly string YELLOW = "\u001b[33m"; public static readonly string BLUE = "\u001b[34m"; public static readonly string MAGENTA = "\u001b[35m"; public static readonly string CYAN = "\u001b[36m"; public static readonly string WHITE = "\u001b[37m"; public static readonly string GRAY = "\u001b[90m"; public static readonly string ORANGE = TextFromRGB(255, 165, 0); public static readonly string PINK = TextFromRGB(255, 192, 203); public static readonly string BRIGHT_RED = "\u001b[91m"; public static readonly string BRIGHT_GREEN = "\u001b[92m"; public static readonly string BRIGHT_YELLOW = "\u001b[93m"; public static readonly string BRIGHT_BLUE = "\u001b[94m"; public static readonly string BRIGHT_MAGENTA = "\u001b[95m"; public static readonly string BRIGHT_CYAN = "\u001b[96m"; public static readonly string BRIGHT_WHITE = "\u001b[97m"; public static readonly string BRIGHT_ORANGE = TextFromRGB(255, 153, 28); public static readonly string BRIGHT_PINK = TextFromRGB(244, 160, 250); public static readonly string BG_BLACK = "\u001b[40m"; public static readonly string BG_RED = "\u001b[41m"; public static readonly string BG_GREEN = "\u001b[42m"; public static readonly string BG_YELLOW = "\u001b[43m"; public static readonly string BG_BLUE = "\u001b[44m"; public static readonly string BG_MAGENTA = "\u001b[45m"; public static readonly string BG_CYAN = "\u001b[46m"; public static readonly string BG_WHITE = "\u001b[47m"; public static readonly string BG_GRAY = "\u001b[100m"; public static readonly string BG_ORANGE = BGFromRGB(255, 165, 0); public static readonly string BG_PINK = BGFromRGB(255, 192, 203); public static readonly string BG_BRIGHT_RED = "\u001b[101m"; public static readonly string BG_BRIGHT_GREEN = BGFromRGB(48, 255, 62); public static readonly string BG_BRIGHT_YELLOW = "\u001b[103m"; public static readonly string BG_BRIGHT_BLUE = "\u001b[104m"; public static readonly string BG_BRIGHT_MAGENTA = "\u001b[105m"; public static readonly string BG_BRIGHT_CYAN = BGFromRGB(115, 255, 250); public static readonly string BG_BRIGHT_WHITE = "\u001b[107m"; public static readonly string BG_BRIGHT_ORANGE = BGFromRGB(255, 153, 28); public static readonly string BG_BRIGHT_PINK = BGFromRGB(244, 160, 250); public static readonly string BLACK_BRIGHT = "\u001b[90m"; public static readonly string RED_BRIGHT = "\u001b[91m"; public static readonly string GREEN_BRIGHT = "\u001b[92m"; public static readonly string YELLOW_BRIGHT = "\u001b[93m"; public static readonly string BLUE_BRIGHT = "\u001b[94m"; public static readonly string MAGENTA_BRIGHT = "\u001b[95m"; public static readonly string CYAN_BRIGHT = "\u001b[96m"; public static readonly string WHITE_BRIGHT = "\u001b[97m"; private static bool IsColourSupported(int r, int g, int b) { if (r < 0 || r > 255 || g < 0 || g > 255 || b < 0 || b > 255) { throw new ArgumentException("Invalid Colour: Colour code must be set between 0 and 255."); } return true; } public static string TextFromRGB(int r, int g, int b) { if (IsColourSupported(r, g, b)) { return $"\u001b[38;2;{r};{g};{b}m"; } return string.Empty; } public static string BGFromRGB(int r, int g, int b) { if (IsColourSupported(r, g, b)) { return $"\u001b[48;2;{r};{g};{b}m"; } return string.Empty; } } [BepInPlugin("n1h1lius.valheimdbdumper", "Valheim-DB-Dumper", "1.0.0")] public class ValheimDBDumper : BaseUnityPlugin { [HarmonyPatch(typeof(Terminal), "Awake")] public static class Terminal_Awake_Patch { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static Func<string, bool> <>9__0_1; public static Func<string, bool> <>9__0_2; public static Func<string, bool> <>9__0_3; public static Func<string, bool> <>9__0_4; public static ConsoleEvent <>9__0_0; internal void <Postfix>b__0_0(ConsoleEventArgs args) { <>c__DisplayClass0_0 CS$<>8__locals0 = new <>c__DisplayClass0_0 { args = args }; if (CS$<>8__locals0.args.Args == null || CS$<>8__locals0.args.Args.Length < 2) { PrintHelp(CS$<>8__locals0.args); return; } if ((Object)(object)ObjectDB.instance == (Object)null || ObjectDB.instance.m_items.Count == 0) { CS$<>8__locals0.args.Context.AddString("<color=red>[Valheim DBDumper] Error: You must be inside a world with your character to dump data.</color>"); return; } try { string value = ConfigExportPath.Value; if (!Directory.Exists(value)) { Directory.CreateDirectory(value); } ExtractEmbeddedTools(value); string text = CS$<>8__locals0.args.Args[1].ToLower(); _activeExports = ((!(text == "all")) ? 1 : 5); bool exportIcons = !CS$<>8__locals0.args.Args.Any((string a) => a.Equals("--no-icon", StringComparison.OrdinalIgnoreCase)); bool exportJson = !CS$<>8__locals0.args.Args.Any((string a) => a.Equals("--no-json", StringComparison.OrdinalIgnoreCase)); bool exportPrefab = !CS$<>8__locals0.args.Args.Any((string a) => a.Equals("--no-prefab", StringComparison.OrdinalIgnoreCase)); bool exportModel3d = !CS$<>8__locals0.args.Args.Any((string a) => a.Equals("--no-model3d", StringComparison.OrdinalIgnoreCase)); if (text == "all") { LogSystem.Log("Exporting all database structures..."); } if (text == "all" || text == "recipes") { if (text != "all") { LogSystem.Log("Exporting manufacturing recipes..."); } ((MonoBehaviour)Instance).StartCoroutine(RecipeExporter.ExportRecipesCoroutine(value, CS$<>8__locals0.args, exportJs