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 components { get; set; } = new List(); public List children { get; set; } = new List(); } public class ComponentData { public string type { get; set; } public Dictionary fields { get; set; } = new Dictionary(); } 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 drops { get; set; } = new List(); } 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 d__0 : IEnumerator, 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 5__1; private string 5__2; private string 5__3; private string 5__4; private string 5__5; private List 5__6; private List 5__7; private int 5__8; private int 5__9; private GameObject 5__10; private Character 5__11; private string 5__12; private string 5__13; private CharacterDrop 5__14; private List.Enumerator <>s__15; private Drop 5__16; private ItemDrop 5__17; private CreatureDataDump 5__18; private List.Enumerator <>s__19; private Drop 5__20; private string 5__21; private string 5__22; private string 5__23; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__0(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { 5__1 = null; 5__2 = null; 5__3 = null; 5__4 = null; 5__5 = null; 5__6 = null; 5__7 = null; 5__10 = null; 5__11 = null; 5__12 = null; 5__13 = null; 5__14 = null; <>s__15 = default(List.Enumerator); 5__16 = null; 5__17 = null; 5__18 = null; <>s__19 = default(List.Enumerator); 5__20 = null; 5__21 = null; 5__22 = null; 5__23 = null; <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; 5__1 = Path.Combine(baseFolder, "data", "creatures"); 5__2 = Path.Combine(baseFolder, "icons"); 5__3 = Path.Combine(baseFolder, "prefabs", "creatures"); 5__4 = Path.Combine(baseFolder, "models", "creatures"); 5__5 = Path.Combine(baseFolder, "textures", "creatures"); if (exportJson) { Directory.CreateDirectory(5__1); } if (exportIcons) { Directory.CreateDirectory(5__2); } if (exportPrefab) { Directory.CreateDirectory(5__3); } if (exportModel3d) { Directory.CreateDirectory(5__4); Directory.CreateDirectory(5__5); } 5__6 = ZNetScene.instance.m_prefabs; 5__7 = new List(); args.Context.AddString($"[Valheim DBDumper] Scanning {5__6.Count} game prefabs for creatures..."); LogSystem.Info($"Scanning {5__6.Count} game prefabs for creatures..."); <>2__current = null; <>1__state = 1; return true; case 1: <>1__state = -1; 5__8 = 0; 5__9 = 0; goto IL_0785; case 2: { <>1__state = -1; goto IL_074f; } IL_0785: if (5__9 < 5__6.Count) { 5__10 = 5__6[5__9]; if (!((Object)(object)5__10 == (Object)null)) { 5__11 = 5__10.GetComponent(); if (!((Object)(object)5__11 == (Object)null)) { 5__12 = ((Object)5__10).name; 5__13 = 5__11.m_name; if (!5__12.ToLower().Contains("player")) { 5__14 = 5__10.GetComponent(); if (exportIcons && (Object)(object)5__14 != (Object)null && 5__14.m_drops != null) { Directory.CreateDirectory(Path.Combine(5__2, "Creatures")); <>s__15 = 5__14.m_drops.GetEnumerator(); try { while (<>s__15.MoveNext()) { 5__16 = <>s__15.Current; if ((Object)(object)5__16.m_prefab != (Object)null && ((Object)5__16.m_prefab).name.ToLower().Contains("trophy")) { 5__17 = 5__16.m_prefab.GetComponent(); if ((Object)(object)5__17 != (Object)null) { ItemData itemData = 5__17.m_itemData; if (itemData != null && itemData.m_shared?.m_icons?.Length > 0) { SaveCroppedSpriteAsPNG(5__17.m_itemData.m_shared.m_icons[0], Path.Combine(5__2, "Creatures", 5__12 + ".png")); 5__8++; break; } } 5__17 = null; } 5__16 = null; } } finally { ((IDisposable)<>s__15).Dispose(); } <>s__15 = default(List.Enumerator); } if (exportJson) { 5__18 = new CreatureDataDump { prefab_name = 5__12, creature_name = TranslateToken(5__13), creature_rawName = 5__13, max_health = 5__11.m_health, faction = ((object)(Faction)(ref 5__11.m_faction)).ToString(), tolerate_water = 5__11.m_tolerateWater, tolerate_fire = 5__11.m_tolerateFire }; if ((Object)(object)5__14 != (Object)null && 5__14.m_drops != null) { <>s__19 = 5__14.m_drops.GetEnumerator(); try { while (<>s__19.MoveNext()) { 5__20 = <>s__19.Current; if (5__20 != null && !((Object)(object)5__20.m_prefab == (Object)null)) { 5__18.drops.Add(new CreatureDropData { item_prefab = ((Object)5__20.m_prefab).name, min_amount = 5__20.m_amountMin, max_amount = 5__20.m_amountMax, chance_percent = 5__20.m_chance * 100f, level_multiplier = 5__20.m_levelMultiplier }); 5__20 = null; } } } finally { ((IDisposable)<>s__19).Dispose(); } <>s__19 = default(List.Enumerator); } 5__7.Add(5__18); 5__18 = null; } if (exportPrefab) { 5__21 = Path.Combine(5__3, 5__12 + ".json"); DumpPrefabHierarchyToJson(5__10, 5__21); 5__8++; 5__21 = null; } if (exportModel3d) { 5__22 = Path.Combine(5__4, 5__12 + ".obj"); ExportPrefabToObj(5__10, 5__22); ExportCreatureSkinTexture(5__10, 5__5, 5__12); 5__8++; 5__22 = null; } if (5__7.Count % 20 == 0) { args.Context.AddString($"[Valheim DBDumper] Processed {5__7.Count} unique creatures..."); } if (5__8 >= 30) { 5__8 = 0; <>2__current = null; <>1__state = 2; return true; } goto IL_074f; } } } goto IL_0773; } if (exportJson && 5__7.Count > 0) { 5__23 = JsonConvert.SerializeObject((object)5__7, (Formatting)1); File.WriteAllText(Path.Combine(5__1, "creatures.json"), 5__23); 5__23 = null; } args.Context.AddString("[Valheim DBDumper] Creatures module finished! Geometries and skin textures successfully dumped."); LogSystem.Success("Creatures module finished! Geometries and skin textures successfully dumped."); onFinished?.Invoke(); return false; IL_0773: 5__9++; goto IL_0785; IL_074f: 5__10 = null; 5__11 = null; 5__12 = null; 5__13 = null; 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(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 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(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[] 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(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(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 d__0 : IEnumerator, 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 5__1; private string 5__2; private string 5__3; private string 5__4; private string 5__5; private List 5__6; private List 5__7; private int 5__8; private int 5__9; private GameObject 5__10; private ItemDrop 5__11; private SharedData 5__12; private string 5__13; private Sprite[] 5__14; private ItemDataDump 5__15; private string 5__16; private string 5__17; private string 5__18; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__0(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { 5__1 = null; 5__2 = null; 5__3 = null; 5__4 = null; 5__5 = null; 5__6 = null; 5__7 = null; 5__10 = null; 5__11 = null; 5__12 = null; 5__13 = null; 5__14 = null; 5__15 = null; 5__16 = null; 5__17 = null; 5__18 = null; <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; 5__1 = Path.Combine(baseFolder, "data", "items"); 5__2 = Path.Combine(baseFolder, "icons"); 5__3 = Path.Combine(baseFolder, "prefabs", "items"); 5__4 = Path.Combine(baseFolder, "models", "items"); 5__5 = Path.Combine(baseFolder, "textures", "items"); if (exportJson) { Directory.CreateDirectory(5__1); } if (exportIcons) { Directory.CreateDirectory(5__2); } if (exportPrefab) { Directory.CreateDirectory(5__3); } if (exportModel3d) { Directory.CreateDirectory(5__4); Directory.CreateDirectory(5__5); } 5__6 = ObjectDB.instance.m_items; 5__7 = new List(); args.Context.AddString($"[Valheim DBDumper] Processing {5__6.Count} items into unified pipeline..."); LogSystem.Info($"Processing {5__6.Count} items into unified pipeline..."); <>2__current = null; <>1__state = 1; return true; case 1: <>1__state = -1; 5__8 = 0; 5__9 = 0; goto IL_0639; case 2: { <>1__state = -1; goto IL_060a; } IL_0639: if (5__9 < 5__6.Count) { 5__10 = 5__6[5__9]; if (!((Object)(object)5__10 == (Object)null)) { 5__11 = 5__10.GetComponent(); if (!((Object)(object)5__11 == (Object)null) && 5__11.m_itemData != null) { 5__12 = 5__11.m_itemData.m_shared; 5__13 = ((Object)5__10).name; if (exportIcons) { Directory.CreateDirectory(Path.Combine(5__2, "Items")); 5__14 = 5__12.m_icons; if (5__14 != null && 5__14.Length != 0 && (Object)(object)5__14[0] != (Object)null) { SaveCroppedSpriteAsPNG(5__14[0], Path.Combine(5__2, "Items", 5__13 + ".png")); 5__8++; } 5__14 = null; } if (exportJson) { 5__15 = new ItemDataDump { prefab_name = 5__13, item_name = TranslateToken(5__12.m_name), item_rawName = 5__12.m_name, description = TranslateToken(5__12.m_description), type = ((object)(ItemType)(ref 5__12.m_itemType)).ToString(), weight = 5__12.m_weight, max_stack = 5__12.m_maxStackSize, max_durability = 5__12.m_maxDurability, armor = 5__12.m_armor, blunt_damage = 5__12.m_damages.m_blunt, slash_damage = 5__12.m_damages.m_slash, pierce_damage = 5__12.m_damages.m_pierce, chop_damage = 5__12.m_damages.m_chop, pickaxe_damage = 5__12.m_damages.m_pickaxe, fire_damage = 5__12.m_damages.m_fire, frost_damage = 5__12.m_damages.m_frost, lightning_damage = 5__12.m_damages.m_lightning, poison_damage = 5__12.m_damages.m_poison, spirit_damage = 5__12.m_damages.m_spirit }; 5__7.Add(5__15); 5__15 = null; } if (exportPrefab) { 5__16 = Path.Combine(5__3, 5__13 + ".json"); DumpPrefabHierarchyToJson(5__10, 5__16); 5__8++; 5__16 = null; } if (exportModel3d) { 5__17 = Path.Combine(5__4, 5__13 + ".obj"); ExportPrefabToObj(5__10, 5__17); ExportItemSkinTexture(5__10, 5__5, 5__13); 5__8++; 5__17 = null; } if (5__9 > 0 && 5__9 % 150 == 0) { args.Context.AddString($"[Valheim DBDumper] Processed {5__9}/{5__6.Count} unique items..."); } if (5__8 >= 25) { 5__8 = 0; <>2__current = null; <>1__state = 2; return true; } goto IL_060a; } } goto IL_0627; } if (exportJson && 5__7.Count > 0) { 5__18 = JsonConvert.SerializeObject((object)5__7, (Formatting)1); File.WriteAllText(Path.Combine(5__1, "items.json"), 5__18); 5__18 = null; } args.Context.AddString("[Valheim DBDumper] Item module finished processing successfully! Models and textures sync'd."); LogSystem.Success("Item module finished processing successfully! Models and textures sync'd."); onFinished?.Invoke(); return false; IL_060a: 5__10 = null; 5__11 = null; 5__12 = null; 5__13 = null; goto IL_0627; IL_0627: 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(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 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[] 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(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(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(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 d__0 : IEnumerator, 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 5__1; private string 5__2; private string 5__3; private string 5__4; private string 5__5; private List 5__6; private List 5__7; private int 5__8; private int 5__9; private GameObject 5__10; private Pickable 5__11; private string 5__12; private GameObject 5__13; private string 5__14; private ItemDrop 5__15; private string 5__16; private PickableDataDump 5__17; private string 5__18; private string 5__19; private string 5__20; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__0(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { 5__1 = null; 5__2 = null; 5__3 = null; 5__4 = null; 5__5 = null; 5__6 = null; 5__7 = null; 5__10 = null; 5__11 = null; 5__12 = null; 5__13 = null; 5__14 = null; 5__15 = null; 5__16 = null; 5__17 = null; 5__18 = null; 5__19 = null; 5__20 = null; <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; 5__1 = Path.Combine(baseFolder, "data", "pickables"); 5__2 = Path.Combine(baseFolder, "icons"); 5__3 = Path.Combine(baseFolder, "prefabs", "pickables"); 5__4 = Path.Combine(baseFolder, "models", "pickables"); 5__5 = Path.Combine(baseFolder, "textures", "pickables"); if (exportJson) { Directory.CreateDirectory(5__1); } if (exportIcons) { Directory.CreateDirectory(5__2); } if (exportPrefab) { Directory.CreateDirectory(5__3); } if (exportModel3d) { Directory.CreateDirectory(5__4); Directory.CreateDirectory(5__5); } 5__6 = ZNetScene.instance.m_prefabs; 5__7 = new List(); args.Context.AddString($"[Valheim DBDumper] Scanning {5__6.Count} game prefabs for pickables..."); LogSystem.Info($"Scanning {5__6.Count} game prefabs for pickables..."); <>2__current = null; <>1__state = 1; return true; case 1: <>1__state = -1; 5__8 = 0; 5__9 = 0; goto IL_05ad; case 2: { <>1__state = -1; goto IL_0577; } IL_05ad: if (5__9 < 5__6.Count) { 5__10 = 5__6[5__9]; if (!((Object)(object)5__10 == (Object)null)) { 5__11 = 5__10.GetComponent(); if (!((Object)(object)5__11 == (Object)null)) { 5__12 = ((Object)5__10).name; 5__13 = 5__11.m_itemPrefab; 5__14 = (((Object)(object)5__13 != (Object)null) ? ((Object)5__13).name : "None"); if (exportIcons && (Object)(object)5__13 != (Object)null) { Directory.CreateDirectory(Path.Combine(5__2, "Pickables")); 5__15 = 5__13.GetComponent(); if ((Object)(object)5__15 != (Object)null) { ItemData itemData = 5__15.m_itemData; if (itemData != null && itemData.m_shared?.m_icons?.Length > 0) { SaveCroppedSpriteAsPNG(5__15.m_itemData.m_shared.m_icons[0], Path.Combine(5__2, "Pickables", 5__12 + ".png")); 5__8++; } } 5__15 = null; } if (exportJson) { 5__16 = (string.IsNullOrEmpty(((Object)5__11).name) ? 5__12 : ((Object)5__11).name); 5__17 = new PickableDataDump { prefab_name = 5__12, pickable_name = TranslateToken(5__16), pickable_rawName = 5__16, drop_item_prefab = 5__14, min_amount = 5__11.m_amount, max_amount = 5__11.m_amount, respawn_minutes = (int)5__11.m_respawnTimeMinutes }; 5__7.Add(5__17); 5__16 = null; 5__17 = null; } if (exportPrefab) { 5__18 = Path.Combine(5__3, 5__12 + ".json"); DumpPrefabHierarchyToJson(5__10, 5__18); 5__8++; 5__18 = null; } if (exportModel3d) { 5__19 = Path.Combine(5__4, 5__12 + ".obj"); ExportPrefabToObj(5__10, 5__19); ExportPickableSkinTexture(5__10, 5__5, 5__12); 5__8++; 5__19 = null; } if (5__7.Count % 15 == 0) { args.Context.AddString($"[Valheim DBDumper] Processed {5__7.Count} unique pickables..."); } if (5__8 >= 30) { 5__8 = 0; <>2__current = null; <>1__state = 2; return true; } goto IL_0577; } } goto IL_059b; } if (exportJson && 5__7.Count > 0) { 5__20 = JsonConvert.SerializeObject((object)5__7, (Formatting)1); File.WriteAllText(Path.Combine(5__1, "pickables.json"), 5__20); 5__20 = null; } args.Context.AddString($"[Valheim DBDumper] Pickables module finished! Saved {5__7.Count} environment assets and geometries."); LogSystem.Success($"Pickables module finished! Saved {5__7.Count} environment assets and geometries."); onFinished?.Invoke(); return false; IL_0577: 5__10 = null; 5__11 = null; 5__12 = null; 5__13 = null; 5__14 = null; goto IL_059b; IL_059b: 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(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 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[] 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(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(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(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 resources { get; set; } = new List(); } 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 d__0 : IEnumerator, 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 5__1; private string 5__2; private List 5__3; private List 5__4; private HashSet 5__5; private int 5__6; private List.Enumerator <>s__7; private GameObject 5__8; private ItemDrop 5__9; private PieceTable 5__10; private string 5__11; private List.Enumerator <>s__12; private GameObject 5__13; private string 5__14; private Piece 5__15; private string 5__16; private PieceDataDump 5__17; private Requirement[] <>s__18; private int <>s__19; private Requirement 5__20; private string 5__21; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public 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(); } } 5__1 = null; 5__2 = null; 5__3 = null; 5__4 = null; 5__5 = null; <>s__7 = default(List.Enumerator); 5__8 = null; 5__9 = null; 5__10 = null; 5__11 = null; <>s__12 = default(List.Enumerator); 5__13 = null; 5__14 = null; 5__15 = null; 5__16 = null; 5__17 = null; <>s__18 = null; 5__20 = null; 5__21 = null; <>1__state = -2; } private bool MoveNext() { try { switch (<>1__state) { default: return false; case 0: <>1__state = -1; 5__1 = Path.Combine(baseFolder, "data", "pieces"); 5__2 = Path.Combine(baseFolder, "icons"); if (exportJson) { Directory.CreateDirectory(5__1); } if (exportIcons) { Directory.CreateDirectory(5__2); } 5__3 = ObjectDB.instance.m_items; 5__4 = new List(); 5__5 = new HashSet(); args.Context.AddString("[Valheim DBDumper] Scanning tools for building pieces..."); LogSystem.Info("Scanning tools for building pieces..."); <>2__current = null; <>1__state = 1; return true; case 1: <>1__state = -1; 5__6 = 0; <>s__7 = 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()) { 5__8 = <>s__7.Current; if ((Object)(object)5__8 == (Object)null) { continue; } 5__9 = 5__8.GetComponent(); if (!((Object)(object)5__9 == (Object)null) && 5__9.m_itemData != null) { 5__10 = 5__9.m_itemData.m_shared.m_buildPieces; if (!((Object)(object)5__10 == (Object)null) && 5__10.m_pieces != null) { break; } } continue; } <>m__Finally1(); <>s__7 = default(List.Enumerator); if (exportJson && 5__4.Count > 0) { 5__21 = JsonConvert.SerializeObject((object)5__4, (Formatting)1); File.WriteAllText(Path.Combine(5__1, "pieces.json"), 5__21); 5__21 = null; } args.Context.AddString($"[Valheim DBDumper] Pieces module finished! Saved {5__4.Count} unique structures."); LogSystem.Success($"Pieces module finished! Saved {5__4.Count} unique structures."); onFinished?.Invoke(); return false; } Directory.CreateDirectory(Path.Combine(5__2, "Pieces")); 5__11 = ((Object)5__8).name; <>s__12 = 5__10.m_pieces.GetEnumerator(); <>1__state = -4; goto IL_0582; IL_056c: 5__14 = null; 5__15 = null; 5__13 = null; goto IL_0582; IL_0582: while (<>s__12.MoveNext()) { 5__13 = <>s__12.Current; if ((Object)(object)5__13 == (Object)null) { continue; } 5__14 = ((Object)5__13).name; if (5__5.Contains(5__14)) { continue; } 5__15 = 5__13.GetComponent(); if ((Object)(object)5__15 == (Object)null) { continue; } goto IL_028e; } <>m__Finally2(); <>s__12 = default(List.Enumerator); 5__9 = null; 5__10 = null; 5__11 = null; 5__8 = null; goto IL_05c2; IL_028e: if (exportIcons && (Object)(object)5__15.m_icon != (Object)null) { SaveCroppedSpriteAsPNG(5__15.m_icon, Path.Combine(5__2, "Pieces", 5__14 + ".png")); 5__6++; } if (exportJson) { 5__16 = (((Object)(object)5__15.m_craftingStation != (Object)null) ? 5__15.m_craftingStation.m_name : "None"); 5__17 = new PieceDataDump { prefab_name = 5__14, piece_name = TranslateToken(5__15.m_name), piece_rawName = 5__15.m_name, description = TranslateToken(5__15.m_description), category = ((object)(PieceCategory)(ref 5__15.m_category)).ToString(), primary_tool = 5__11, required_station = 5__16 }; if (5__15.m_resources != null) { <>s__18 = 5__15.m_resources; for (<>s__19 = 0; <>s__19 < <>s__18.Length; <>s__19++) { 5__20 = <>s__18[<>s__19]; if (5__20 != null && !((Object)(object)5__20.m_resItem == (Object)null)) { 5__17.resources.Add(new PieceRequirementData { item_prefab = ((Object)((Component)5__20.m_resItem).gameObject).name, amount = 5__20.m_amount, recover = 5__20.m_recover }); 5__20 = null; } } <>s__18 = null; } 5__4.Add(5__17); 5__16 = null; 5__17 = null; } 5__5.Add(5__14); if (5__5.Count % 50 == 0) { args.Context.AddString($"[Valheim DBDumper] Processed {5__5.Count} unique building pieces..."); } if (5__6 >= 25) { 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(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 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 requirements { get; set; } = new List(); } 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 d__0 : IEnumerator, 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 5__1; private string 5__2; private List 5__3; private List 5__4; private int 5__5; private int 5__6; private Recipe 5__7; private string 5__8; private Sprite[] 5__9; private string 5__10; private string 5__11; private RecipeData 5__12; private Requirement[] <>s__13; private int <>s__14; private Requirement 5__15; private string 5__16; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__0(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { 5__1 = null; 5__2 = null; 5__3 = null; 5__4 = null; 5__7 = null; 5__8 = null; 5__9 = null; 5__10 = null; 5__11 = null; 5__12 = null; <>s__13 = null; 5__15 = null; 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; 5__1 = Path.Combine(baseFolder, "data", "recipes"); 5__2 = Path.Combine(baseFolder, "icons"); if (exportJson) { Directory.CreateDirectory(5__1); } if (exportIcons) { Directory.CreateDirectory(5__2); } 5__3 = ObjectDB.instance.m_recipes; 5__4 = new List(); args.Context.AddString($"[Valheim DBDumper] Processing {5__3.Count} recipes..."); LogSystem.Info($"Processing {5__3.Count} recipes..."); 5__5 = 0; Directory.CreateDirectory(Path.Combine(5__2, "Recipes")); 5__6 = 0; goto IL_04a1; IL_04a1: if (5__6 < 5__3.Count) { 5__7 = 5__3[5__6]; if ((Object)(object)5__7 == (Object)null || (Object)(object)5__7.m_item == (Object)null) { goto IL_048f; } 5__8 = ((Object)((Component)5__7.m_item).gameObject).name; if (exportIcons) { 5__9 = 5__7.m_item.m_itemData.m_shared.m_icons; if (5__9 != null && 5__9.Length != 0 && (Object)(object)5__9[0] != (Object)null) { SaveCroppedSpriteAsPNG(5__9[0], Path.Combine(5__2, "Recipes", 5__8 + ".png")); 5__5++; } 5__9 = null; } if (exportJson) { 5__10 = 5__7.m_item.m_itemData.m_shared.m_name; 5__11 = (((Object)(object)5__7.m_craftingStation != (Object)null) ? 5__7.m_craftingStation.m_name : "Hand"); 5__12 = new RecipeData { prefab_name = 5__8, item_name = TranslateToken(5__10), item_rawName = 5__10, crafting_station = 5__11, min_station_level = 5__7.m_minStationLevel, amount = 5__7.m_amount }; if (5__7.m_resources != null) { <>s__13 = 5__7.m_resources; for (<>s__14 = 0; <>s__14 < <>s__13.Length; <>s__14++) { 5__15 = <>s__13[<>s__14]; if (5__15 != null && !((Object)(object)5__15.m_resItem == (Object)null)) { 5__12.requirements.Add(new RequirementData { item_prefab = ((Object)((Component)5__15.m_resItem).gameObject).name, amount = 5__15.m_amount, amount_per_level = 5__15.m_amountPerLevel }); 5__15 = null; } } <>s__13 = null; } 5__4.Add(5__12); 5__10 = null; 5__11 = null; 5__12 = null; } if (5__6 > 0 && 5__6 % 150 == 0) { args.Context.AddString($"[Valheim DBDumper] Processed {5__6}/{5__3.Count} recipes..."); } if (5__5 >= 25) { 5__5 = 0; <>2__current = null; <>1__state = 1; return true; } goto IL_0480; } if (exportJson && 5__4.Count > 0) { 5__16 = JsonConvert.SerializeObject((object)5__4, (Formatting)1); File.WriteAllText(Path.Combine(5__1, "recipes.json"), 5__16); 5__16 = null; } args.Context.AddString("[Valheim DBDumper] Recipe module finished processing successfully!"); LogSystem.Success("Recipe module finished processing successfully!"); onFinished?.Invoke(); return false; IL_0480: 5__7 = null; 5__8 = null; goto IL_048f; IL_048f: 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(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 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 <>9__0_1; public static Func <>9__0_2; public static Func <>9__0_3; public static Func <>9__0_4; public static ConsoleEvent <>9__0_0; internal void 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("[Valheim DBDumper] Error: You must be inside a world with your character to dump data."); 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, exportJson, exportIcons, delegate { CheckFinished(CS$<>8__locals0.args); })); } if (text == "all" || text == "items") { if (text != "all") { LogSystem.Log("Exporting items..."); } ((MonoBehaviour)Instance).StartCoroutine(ItemsExporter.ExportItemsCoroutine(value, CS$<>8__locals0.args, exportJson, exportIcons, exportPrefab, exportModel3d, delegate { CheckFinished(CS$<>8__locals0.args); })); } if (text == "all" || text == "pieces") { if (text != "all") { LogSystem.Log("Exporting pieces..."); } ((MonoBehaviour)Instance).StartCoroutine(PiecesExporter.ExportPiecesCoroutine(value, CS$<>8__locals0.args, exportJson, exportIcons, delegate { CheckFinished(CS$<>8__locals0.args); })); } if (text == "all" || text == "creatures") { if (text != "all") { LogSystem.Log("Exporting creatures..."); } ((MonoBehaviour)Instance).StartCoroutine(CreaturesExporter.ExportCreaturesCoroutine(value, CS$<>8__locals0.args, exportJson, exportIcons, exportPrefab, exportModel3d, delegate { CheckFinished(CS$<>8__locals0.args); })); } if (text == "all" || text == "pickables") { if (text != "all") { LogSystem.Log("Exporting pickables..."); } ((MonoBehaviour)Instance).StartCoroutine(PickablesExporter.ExportPickablesCoroutine(value, CS$<>8__locals0.args, exportJson, exportIcons, exportPrefab, exportModel3d, delegate { CheckFinished(CS$<>8__locals0.args); })); } else if (text != "all" && text != "recipes" && text != "items" && text != "pieces" && text != "creatures" && text != "pickables") { CS$<>8__locals0.args.Context.AddString("[Valheim DBDumper] Unknown category '" + text + "'."); PrintHelp(CS$<>8__locals0.args); } } catch (Exception ex) { CS$<>8__locals0.args.Context.AddString("[Valheim DBDumper] Critical error: " + ex.Message + ""); LogSystem.Error($"Dump failed: {ex}"); } } internal bool b__0_1(string a) { return a.Equals("--no-icon", StringComparison.OrdinalIgnoreCase); } internal bool b__0_2(string a) { return a.Equals("--no-json", StringComparison.OrdinalIgnoreCase); } internal bool b__0_3(string a) { return a.Equals("--no-prefab", StringComparison.OrdinalIgnoreCase); } internal bool b__0_4(string a) { return a.Equals("--no-model3d", StringComparison.OrdinalIgnoreCase); } } [CompilerGenerated] private sealed class <>c__DisplayClass0_0 { public ConsoleEventArgs args; internal void b__5() { CheckFinished(args); } internal void b__6() { CheckFinished(args); } internal void b__7() { CheckFinished(args); } internal void b__8() { CheckFinished(args); } internal void b__9() { CheckFinished(args); } } public static void Postfix(Terminal __instance) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown object obj = <>c.<>9__0_0; if (obj == null) { ConsoleEvent val = delegate(ConsoleEventArgs args) { if (args.Args == null || args.Args.Length < 2) { PrintHelp(args); } else { if (!((Object)(object)ObjectDB.instance == (Object)null) && ObjectDB.instance.m_items.Count != 0) { try { string value = ConfigExportPath.Value; if (!Directory.Exists(value)) { Directory.CreateDirectory(value); } ExtractEmbeddedTools(value); string text = args.Args[1].ToLower(); _activeExports = ((!(text == "all")) ? 1 : 5); bool exportIcons = !args.Args.Any((string a) => a.Equals("--no-icon", StringComparison.OrdinalIgnoreCase)); bool exportJson = !args.Args.Any((string a) => a.Equals("--no-json", StringComparison.OrdinalIgnoreCase)); bool exportPrefab = !args.Args.Any((string a) => a.Equals("--no-prefab", StringComparison.OrdinalIgnoreCase)); bool exportModel3d = !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, args, exportJson, exportIcons, delegate { CheckFinished(args); })); } if (text == "all" || text == "items") { if (text != "all") { LogSystem.Log("Exporting items..."); } ((MonoBehaviour)Instance).StartCoroutine(ItemsExporter.ExportItemsCoroutine(value, args, exportJson, exportIcons, exportPrefab, exportModel3d, delegate { CheckFinished(args); })); } if (text == "all" || text == "pieces") { if (text != "all") { LogSystem.Log("Exporting pieces..."); } ((MonoBehaviour)Instance).StartCoroutine(PiecesExporter.ExportPiecesCoroutine(value, args, exportJson, exportIcons, delegate { CheckFinished(args); })); } if (text == "all" || text == "creatures") { if (text != "all") { LogSystem.Log("Exporting creatures..."); } ((MonoBehaviour)Instance).StartCoroutine(CreaturesExporter.ExportCreaturesCoroutine(value, args, exportJson, exportIcons, exportPrefab, exportModel3d, delegate { CheckFinished(args); })); } if (text == "all" || text == "pickables") { if (text != "all") { LogSystem.Log("Exporting pickables..."); } ((MonoBehaviour)Instance).StartCoroutine(PickablesExporter.ExportPickablesCoroutine(value, args, exportJson, exportIcons, exportPrefab, exportModel3d, delegate { CheckFinished(args); })); } else if (text != "all" && text != "recipes" && text != "items" && text != "pieces" && text != "creatures" && text != "pickables") { args.Context.AddString("[Valheim DBDumper] Unknown category '" + text + "'."); PrintHelp(args); } return; } catch (Exception ex) { args.Context.AddString("[Valheim DBDumper] Critical error: " + ex.Message + ""); LogSystem.Error($"Dump failed: {ex}"); return; } } args.Context.AddString("[Valheim DBDumper] Error: You must be inside a world with your character to dump data."); } }; <>c.<>9__0_0 = val; obj = (object)val; } new ConsoleCommand("dumpdb", "Exports game database with filters", (ConsoleEvent)obj, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); } private static void PrintHelp(ConsoleEventArgs args) { args.Context.AddString(""); args.Context.AddString("=== Valheim DBDumper - Help Panel ==="); args.Context.AddString(""); args.Context.AddString("Usage: dumpdb [modifiers]"); args.Context.AddString(""); args.Context.AddString("Available Categories:"); args.Context.AddString(""); args.Context.AddString(" all - Exports absolutely all database structures."); args.Context.AddString(" recipes - Exports manufacturing recipes exclusively."); args.Context.AddString(" items - Exports weapons, armor, and material data."); args.Context.AddString(" pieces - Exports building structures and stations."); args.Context.AddString(" creatures - Exports animals, monsters, and boss drop tables."); args.Context.AddString(" pickables - Exports wild spawns, plants, and ground resource nodes."); args.Context.AddString(""); args.Context.AddString("Optional Modifiers:"); args.Context.AddString(""); args.Context.AddString(" --no-icon - Bypasses texture atlas rendering and PNG extraction completely."); args.Context.AddString(" --no-json - Skips data mapping and JSON generation completely."); args.Context.AddString(" --no-prefab - Skips prefab data mapping and JSON generation completely."); args.Context.AddString(" --no-model3d - Skips Models + Textures mapping and data extraction completely."); args.Context.AddString(""); args.Context.AddString("Example: dumpdb pickables --no-icon"); } private static void ExtractEmbeddedTools(string destinationFolder) { string[] array = new string[2] { "ValheimDBDumper.Tools.index.html", "ValheimDBDumper.Tools.start_server.bat" }; Directory.CreateDirectory(destinationFolder); string[] array2 = array; foreach (string text in array2) { using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(text); if (stream != null) { string path = (text.Substring(text.LastIndexOf('.') + 1).Contains("html") ? "index.html" : "start_server.bat"); string path2 = Path.Combine(destinationFolder, path); using FileStream destination = new FileStream(path2, FileMode.Create); stream.CopyTo(destination); } } } private static void CheckFinished(ConsoleEventArgs args) { _activeExports--; if (_activeExports <= 0) { args.Context.AddString("[Valheim DBDumper] Process Completed Successfuly!"); LogSystem.Success("All export tasks completed successfully."); } } } private const string ModGUID = "n1h1lius.valheimdbdumper"; private const string ModName = "Valheim-DB-Dumper"; private const string ModVersion = "1.0.0"; private static int _activeExports; public static ValheimDBDumper Instance { get; private set; } public static ConfigEntry ConfigExportPath { get; private set; } public static ConfigEntry ConfigDebugMode { get; private set; } public static ConfigEntry ConfigOutputLog { get; private set; } private void Awake() { //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Expected O, but got Unknown Instance = this; string text = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "ValheimDB_Export"); ConfigExportPath = ((BaseUnityPlugin)this).Config.Bind("General", "ExportFolder", text, "Absolute path where the dumper files will be exported. Default: Desktop/ValheimDB_Export"); ConfigDebugMode = ((BaseUnityPlugin)this).Config.Bind("Debug", "DebugMode", false, "Enable debug mode for development purposes."); ConfigOutputLog = ((BaseUnityPlugin)this).Config.Bind("Debug", "OutputLog", true, "Enable logging to the log file."); LogSystem.Init(); LogSystem.SetDebugMode(ConfigDebugMode.Value); LogSystem.SetOutput(ConfigOutputLog.Value, print: false); LogSystem.Log("Export folder configured at: " + ConfigExportPath.Value); LogSystem.Success("Valheim-DB-Dumper v1.0.0 loaded."); Harmony val = new Harmony("n1h1lius.valheimdbdumper"); val.PatchAll(); } } } namespace ValheimDBDumper.Tools { public class LogSystem { private static int VERBOSE_LEVEL = 3; private static bool OUTPUT_LOG = true; private static bool OUTPUT_PRINT = true; private static bool DEBUG_MODE = false; private static bool COLOUR = true; private static string OUTPUT_LOG_FILE = "LogSystem.txt"; private static string OUTPUT_PRINT_FILE = "LogSystem.txt"; private static string RESET = ""; private static string C_TIME = ""; private static string C_FILE = ""; private static string C_METHOD = ""; private static string C_LINE = ""; private static string C_INFO = ""; private static string C_WARN = ""; private static string C_ERROR = ""; private static string C_SUCCESS = ""; private static string C_TEXT = ""; private static string C_PROMPT = ""; private static string C_SEPARATOR = ""; private static readonly ManualLogSource Logger = Logger.CreateLogSource("Valheim-DB-Dumper"); public static void Init() { SetColors(); VERBOSE_LEVEL = 100; OUTPUT_LOG = true; OUTPUT_PRINT = true; DEBUG_MODE = true; COLOUR = true; OUTPUT_LOG_FILE = "LogSystem.txt"; OUTPUT_PRINT_FILE = "LogSystem.txt"; } public static void SetVerboseLevel(int level) { VERBOSE_LEVEL = level; } public static void SetDebugMode(bool mode) { DEBUG_MODE = mode; } public static void SetOutput(bool log, bool print) { OUTPUT_LOG = log; OUTPUT_PRINT = print; } public static void SetOutputFile(string log, string print) { OUTPUT_LOG_FILE = log; OUTPUT_PRINT_FILE = print; } public static void SetColour(bool colour) { COLOUR = colour; } public static void TestLog() { Log("Testing No Colour Log", colour: false); Log("Testing Standard Log"); Warn("Testing Standard Warning"); Error("Testing Standard Error"); Success("Testing Standard Success"); Info("Testing Standard Info"); } public static void Print(string msg) { Logger.LogMessage((object)msg); if (OUTPUT_PRINT) { OutputFile("print", msg); } } private static string InternalLog(string msg) { SetColors(); string[] callerInfo = GetCallerInfo(); string text = C_FILE + "{ " + callerInfo[0] + " }" + C_SEPARATOR + " | " + C_METHOD + "< " + callerInfo[1] + " >" + C_SEPARATOR + " | " + C_LINE + "( " + callerInfo[2] + " )"; string text2 = "{ " + callerInfo[0] + " } | < " + callerInfo[1] + " >"; string result = C_TIME + " " + GetTime() + C_SEPARATOR + " | " + text + C_SEPARATOR + " | " + C_PROMPT + "->> " + C_TEXT + msg + RESET; string msg2 = " " + GetTime() + " | " + text2 + " | ->> " + msg; OutputFile("log", msg2); return result; } private static string InternalAlert(string msg, string bg) { SetColors(); string[] callerInfo = GetCallerInfo(); string text = "{ " + callerInfo[0] + " } | < " + callerInfo[1] + " >"; string text2 = ""; if (bg == C_INFO) { text2 = "[ INFO ]"; } if (bg == C_WARN) { text2 = "[ WARNING ]"; } if (bg == C_ERROR) { text2 = "[ ERROR ]"; } if (bg == C_SUCCESS) { text2 = "[ SUCCESS ]"; } string result = C_TEXT + bg + text2 + " - " + GetTime() + " | " + text + " | ->> " + msg + RESET; string msg2 = " " + text2 + " - " + GetTime() + " | " + text + " | ->> " + msg; OutputFile("log", msg2); return result; } private static void SetColors() { RESET = (COLOUR ? Color.RESET : ""); C_TIME = (COLOUR ? Color.CYAN : ""); C_FILE = (COLOUR ? Color.RED_BRIGHT : ""); C_METHOD = (COLOUR ? Color.BRIGHT_GREEN : ""); C_LINE = (COLOUR ? Color.YELLOW_BRIGHT : ""); C_INFO = (COLOUR ? Color.BG_CYAN : ""); C_WARN = (COLOUR ? Color.BG_ORANGE : ""); C_ERROR = (COLOUR ? Color.BG_RED : ""); C_SUCCESS = (COLOUR ? Color.BG_GREEN : ""); C_TEXT = (COLOUR ? Color.WHITE_BRIGHT : ""); C_PROMPT = (COLOUR ? Color.BRIGHT_ORANGE : ""); C_SEPARATOR = (COLOUR ? Color.BRIGHT_PINK : ""); } private static string[] GetCallerInfo() { StackTrace stackTrace = new StackTrace(fNeedFileInfo: true); string value = typeof(LogSystem).FullName ?? "LogSystem"; for (int i = 0; i < stackTrace.FrameCount; i++) { StackFrame frame = stackTrace.GetFrame(i); if (frame == null) { continue; } MethodBase method = frame.GetMethod(); if (method == null) { continue; } string text = method.DeclaringType?.FullName; if (string.IsNullOrEmpty(text) || text.Contains(value) || text.StartsWith("System.") || text.StartsWith("UnityEngine.") || text.StartsWith("BepInEx.") || text.StartsWith("Mono.") || method.Name.StartsWith("<") || (method.Name.Contains("Awake") && text.Contains("LogSystem"))) { continue; } string text2 = frame.GetFileName() ?? "Unknown"; string name = method.Name; int num = frame.GetFileLineNumber(); if (num == 0) { num = frame.GetILOffset(); if (num == 0) { num = frame.GetNativeOffset(); } } if (text2 == "Unknown" && method.DeclaringType != null) { text2 = method.DeclaringType.Name + ".cs"; } if (num == 0) { num = -1; } return new string[3] { text2, name, num.ToString() }; } return new string[3] { "Unknown", "Unknown", "0" }; } private static string GetTime() { return $"[ {DateTime.Now:HH:mm:ss} ]"; } private static void HandleFolder(string targetPath) { if (!Directory.Exists(targetPath)) { try { Directory.CreateDirectory(targetPath); } catch (Exception ex) { Error("COULD NOT CREATE FOLDER: " + ex.Message); } } } private static void OutputFile(string mode, string msg) { string text = ""; string path = ""; bool flag = false; if (!(mode == "log")) { if (mode == "print") { text = "OUTPUT/PRINT/"; path = OUTPUT_PRINT_FILE; flag = OUTPUT_PRINT; } } else { text = "OUTPUT/LOG/"; path = OUTPUT_LOG_FILE; flag = OUTPUT_LOG; } HandleFolder(text); if (!flag) { return; } string path2 = Path.Combine(text, path); try { File.AppendAllText(path2, msg + Environment.NewLine); } catch (Exception ex) { OUTPUT_LOG = false; OUTPUT_PRINT = false; Error("FILE COULD NOT BE WRITTEN: " + ex.Message); OUTPUT_LOG = true; OUTPUT_PRINT = true; } } public static void Log(int level, string msg) { COLOUR = true; if (level <= VERBOSE_LEVEL) { Logger.LogMessage((object)InternalLog(msg)); } } public static void Log(int level, string msg, bool colour) { COLOUR = colour; if (level <= VERBOSE_LEVEL) { Logger.LogMessage((object)InternalLog(msg)); } } public static void Log(string msg, bool colour) { COLOUR = colour; Logger.LogMessage((object)InternalLog(msg)); } public static void Log(string msg) { COLOUR = true; Logger.LogMessage((object)InternalLog(msg)); } public static void Warn(int level, string msg) { COLOUR = true; if (level <= VERBOSE_LEVEL) { Logger.LogMessage((object)InternalAlert(msg, C_WARN)); } } public static void Warn(int level, string msg, bool colour) { COLOUR = colour; if (level <= VERBOSE_LEVEL) { Logger.LogMessage((object)InternalAlert(msg, C_WARN)); } } public static void Warn(string msg, bool colour) { COLOUR = colour; Logger.LogMessage((object)InternalAlert(msg, C_WARN)); } public static void Warn(string msg) { COLOUR = true; Logger.LogMessage((object)InternalAlert(msg, C_WARN)); } public static void Error(int level, string msg) { COLOUR = true; if (level <= VERBOSE_LEVEL) { Logger.LogMessage((object)InternalAlert(msg, C_ERROR)); } } public static void Error(int level, string msg, bool colour) { COLOUR = colour; if (level <= VERBOSE_LEVEL) { Logger.LogMessage((object)InternalAlert(msg, C_ERROR)); } } public static void Error(string msg, bool colour) { COLOUR = colour; Logger.LogMessage((object)InternalAlert(msg, C_ERROR)); } public static void Error(string msg) { COLOUR = true; Logger.LogMessage((object)InternalAlert(msg, C_ERROR)); } public static void Success(int level, string msg) { COLOUR = true; if (level <= VERBOSE_LEVEL) { Logger.LogMessage((object)InternalAlert(msg, C_SUCCESS)); } } public static void Success(int level, string msg, bool colour) { COLOUR = colour; if (level <= VERBOSE_LEVEL) { Logger.LogMessage((object)InternalAlert(msg, C_SUCCESS)); } } public static void Success(string msg, bool colour) { COLOUR = colour; Logger.LogMessage((object)InternalAlert(msg, C_SUCCESS)); } public static void Success(string msg) { COLOUR = true; Logger.LogMessage((object)InternalAlert(msg, C_SUCCESS)); } public static void Info(int level, string msg) { COLOUR = true; if (level <= VERBOSE_LEVEL) { Logger.LogMessage((object)InternalAlert(msg, C_INFO)); } } public static void Info(int level, string msg, bool colour) { COLOUR = colour; if (level <= VERBOSE_LEVEL) { Logger.LogMessage((object)InternalAlert(msg, C_INFO)); } } public static void Info(string msg, bool colour) { COLOUR = colour; Logger.LogMessage((object)InternalAlert(msg, C_INFO)); } public static void Info(string msg) { COLOUR = true; Logger.LogMessage((object)InternalAlert(msg, C_INFO)); } } }