Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of TarDistillation v0.0.4
BepInEx/plugins/TarDistillation/TarDistillation.dll
Decompiled 18 minutes agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Jotunn; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using Jotunn.Utils; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("hakon")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Distill tar from resinous pine wood in Valheim.")] [assembly: AssemblyFileVersion("0.0.4.0")] [assembly: AssemblyInformationalVersion("0.0.4+2542cfc963a454c4f9e970ec2ed664f1e5b83628")] [assembly: AssemblyProduct("TarDistillation")] [assembly: AssemblyTitle("TarDistillation")] [assembly: AssemblyVersion("0.0.4.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace TarDistillation { internal class ConfigurationManagerAttributes { public bool? IsAdminOnly; } [HarmonyPatch(typeof(Fermenter), "DelayedTap")] internal static class FermenterCharcoalPatch { private const string CoalPrefab = "Coal"; private static void Postfix(Fermenter __instance, int ___m_delayedTapItem, bool ___m_delayedTapItemCheated) { //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: 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_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) int num = TarDistillationPlugin.Cfg?.CoalPerBatch.Value ?? 0; if (num <= 0 || (Object)(object)__instance.m_outputPoint == (Object)null) { return; } ZNetScene instance = ZNetScene.instance; if ((Object)(object)instance == (Object)null) { return; } GameObject prefab = instance.GetPrefab(___m_delayedTapItem); if ((Object)(object)prefab == (Object)null || ((Object)prefab).name != "TyrispikDried") { return; } GameObject prefab2 = instance.GetPrefab("Coal"); ItemDrop val = (((Object)(object)prefab2 == (Object)null) ? null : prefab2.GetComponent<ItemDrop>()); if ((Object)(object)val == (Object)null) { Logger.LogWarning((object)"No Coal prefab found, skipping the charcoal by-product"); return; } for (int i = 0; i < num; i++) { Vector3 val2 = __instance.m_outputPoint.position + Vector3.up * 0.3f + Random.insideUnitSphere * 0.15f; ItemDrop.OnCreateNew(Object.Instantiate<ItemDrop>(val, val2, Quaternion.identity), ___m_delayedTapItemCheated); } } } [HarmonyPatch(typeof(Fermenter), "GetFermentationTime")] internal static class FermenterTimePatch { private static readonly Func<Fermenter, int> GetContent = AccessTools.MethodDelegate<Func<Fermenter, int>>(AccessTools.Method(typeof(Fermenter), "GetContent", (Type[])null, (Type[])null), (object)null, true); private static void Postfix(Fermenter __instance, ref double __result) { int num = TarDistillationPlugin.Cfg?.BurningSeconds.Value ?? 0; if (num <= 0 || __result <= 0.0) { return; } float fermentationDuration = __instance.m_fermentationDuration; if (fermentationDuration <= 0f) { return; } ZNetScene instance = ZNetScene.instance; if (!((Object)(object)instance == (Object)null)) { GameObject prefab = instance.GetPrefab(GetContent(__instance)); if (!((Object)(object)prefab == (Object)null) && !(((Object)prefab).name != "TyrispikDried")) { __result *= (double)fermentationDuration / (double)num; } } } } internal static class ItemVisuals { private const string AssetFolder = "assets"; private static readonly List<GameObject> Dressed = new List<GameObject>(); public static void Apply(GameObject prefab, SharedData shared, string assetName) { if (!((Object)(object)prefab == (Object)null) && TarDistillationPlugin.Cfg.CustomModels.Value) { ApplyIcon(shared, assetName); ApplyModel(prefab, assetName); } } public static void ApplyScale() { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) float value = TarDistillationPlugin.Cfg.ModelScale.Value; foreach (GameObject item in Dressed) { if (!((Object)(object)item == (Object)null)) { MeshFilter[] componentsInChildren = item.GetComponentsInChildren<MeshFilter>(true); for (int i = 0; i < componentsInChildren.Length; i++) { ((Component)componentsInChildren[i]).transform.localScale = Vector3.one * value; } } } } private static void ApplyIcon(SharedData shared, string assetName) { //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) try { Texture2D val = LoadTexture(AssetPath(assetName + "_icon.png")); ((Texture)val).wrapMode = (TextureWrapMode)1; shared.m_icons = (Sprite[])(object)new Sprite[1] { Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f)) }; } catch (Exception ex) { Logger.LogWarning((object)(assetName + ": keeping the vanilla icon (" + Reason(ex) + ")")); } } private static void ApplyModel(GameObject prefab, string assetName) { //IL_0071: 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) try { Mesh val = ObjMesh.Load(AssetPath(assetName + ".obj"), assetName); Texture2D albedo = LoadTexture(AssetPath(assetName + "_albedo.png")); MeshFilter[] componentsInChildren = prefab.GetComponentsInChildren<MeshFilter>(true); if (componentsInChildren.Length == 0) { throw new InvalidDataException("the cloned prefab has no mesh to replace"); } Material val2 = null; float value = TarDistillationPlugin.Cfg.ModelScale.Value; MeshFilter[] array = componentsInChildren; foreach (MeshFilter obj in array) { obj.sharedMesh = val; ((Component)obj).transform.localScale = Vector3.one * value; MeshRenderer component = ((Component)obj).GetComponent<MeshRenderer>(); if (!((Object)(object)component == (Object)null)) { val2 = val2 ?? CloneMaterial(((Renderer)component).sharedMaterial, albedo, assetName); ((Renderer)component).sharedMaterials = (Material[])(object)new Material[1] { val2 }; } } Dressed.Add(prefab); Logger.LogDebug((object)$"{assetName}: {val.vertexCount} vertices over {componentsInChildren.Length} renderer(s)"); } catch (Exception ex) { Logger.LogWarning((object)(assetName + ": keeping the vanilla model (" + Reason(ex) + ")")); } } private static Material CloneMaterial(Material source, Texture2D albedo, string assetName) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Expected O, but got Unknown //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Expected O, but got Unknown //IL_0058: Expected O, but got Unknown if ((Object)(object)source == (Object)null) { throw new InvalidDataException("the cloned prefab has no material to borrow"); } Material val = new Material(source) { name = assetName + "_mat" }; SetTexture(val, "_MainTex", (Texture)(object)albedo); SetColor(val, "_Color", Color.white); SetColor(val, "_MainColor", Color.white); return val; } private static void SetTexture(Material material, string property, Texture texture) { //IL_0013: 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) if (material.HasProperty(property)) { material.SetTexture(property, texture); material.SetTextureScale(property, Vector2.one); material.SetTextureOffset(property, Vector2.zero); } } private static void SetColor(Material material, string property, Color color) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) if (material.HasProperty(property)) { material.SetColor(property, color); } } private static Texture2D LoadTexture(string path) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001d: 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_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown //IL_0050: Expected O, but got Unknown Texture2D val = new Texture2D(2, 2, (TextureFormat)4, true, false) { name = Path.GetFileNameWithoutExtension(path), wrapMode = (TextureWrapMode)0, filterMode = (FilterMode)2, anisoLevel = 4 }; if (!AssetUtils.LoadImage(val, File.ReadAllBytes(path))) { throw new InvalidDataException(Path.GetFileName(path) + " is not a readable image"); } return val; } private static string AssetPath(string fileName) { return Path.Combine(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? ".", "assets"), fileName); } private static string Reason(Exception ex) { if (!(ex is FileNotFoundException) && !(ex is DirectoryNotFoundException)) { return ex.Message; } return "no assets folder beside the DLL - copy it from the package"; } } internal class ModConfig { public readonly ConfigEntry<string> SplittingStation; public readonly ConfigEntry<int> CoreWoodPerBatch; public readonly ConfigEntry<int> ResinPerBatch; public readonly ConfigEntry<string> DryingStation; public readonly ConfigEntry<int> DryingSeconds; public readonly ConfigEntry<int> TarPerBatch; public readonly ConfigEntry<int> CoalPerBatch; public readonly ConfigEntry<int> BurningSeconds; public readonly ConfigEntry<bool> CustomModels; public readonly ConfigEntry<float> ModelScale; public event Action ValuesChanged; public ModConfig(ConfigFile file) { SplittingStation = Bind(file, "1 - Splitting", "Splitting station", "ArtisanTable", "Crafting station the tyrispik recipe is attached to. ArtisanTable puts the whole chain behind Moder, so tar is never cheaper than walking into the plains for it; Workbench or Forge move it much earlier. Read once while the game loads, so it needs a restart - of the server and of every client.", (AcceptableValueBase)(object)CraftingStations.GetAcceptableValueList()); CoreWoodPerBatch = Bind(file, "1 - Splitting", "Core wood per batch", 10, "Core wood (kjerneved) consumed per batch of tyrispik. Written straight into the live recipe, so a new value counts the next time you open the station - no restart.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 100)); ResinPerBatch = Bind(file, "1 - Splitting", "Resin per batch", 5, "Resin consumed per batch of tyrispik, on top of the core wood. Takes effect without a restart, with one exception: 0 removes resin from the recipe entirely, and adding or removing an ingredient only happens while the recipe is being built, so that one waits for a restart.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100)); DryingStation = Bind(file, "2 - Drying", "Drying station", "BlastFurnace", "Smelter-type station that dries raw tyrispik into dried tyrispik, burning fuel as it normally does. BlastFurnace is post-Moder and matches the default splitting station; Smelter or CharcoalKiln make tar reachable in the black forest instead. Read once while the game loads, so it needs a restart - of the server and of every client.", (AcceptableValueBase)(object)Smelters.GetAcceptableValueList()); DryingSeconds = Bind(file, "2 - Drying", "Drying seconds", 0, "Real seconds one tyrispik spends drying. 0 hands the timing back to the station, which dries a spik as fast as it smelts a bar of metal. Examples: 60 is a minute per spik, 300 five minutes, 3600 an hour; the ceiling, 86400, is a full day. Only tyrispik is affected - ore in the same furnace still smelts at the vanilla speed, so you can retime the tar chain without retiming the game. Takes effect immediately, on furnaces already running too.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 86400)); TarPerBatch = Bind(file, "3 - Burning", "Tar per batch", 25, "Tar you get for tapping the fermenter, per batch of dried tyrispik. The default, 25, is half a stack: generous next to the real process, which gave tar worth a fifth of the weight of the wood, but the chain is three stations long and gated behind Moder, so a run is meant to be worth the walk. Drop it to 6 or so if you want the historical trickle instead. Takes effect without a restart, but a fermenter that is already placed and loaded keeps the yield it was built with until its zone reloads.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 50)); CoalPerBatch = Bind(file, "3 - Burning", "Coal per batch", 10, "Charcoal left behind by the burn, handed over together with the tar. A real burn left a lot of it, and 10 comfortably pays back what the furnace spent drying the wood, so a tar run keeps itself in fuel; 0 turns the by-product off if you would rather the chain cost fuel outright. Same timing as the tar: live, but placed fermenters keep their old yield until the zone reloads.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 50)); BurningSeconds = Bind(file, "3 - Burning", "Burning seconds", 0, "Real seconds one batch of dried tyrispik smoulders in the fermenter. 0 keeps the fermenter's own duration, which is the long vanilla mead cycle and the slowest step of the chain. Examples: 600 is ten minutes a batch, 1800 half an hour, 86400 a full day. Only tyrispik is affected - mead still ferments at the vanilla speed. Takes effect immediately, including on fermenters already burning, so lowering it can finish a batch that is under way.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 86400)); CustomModels = BindLocal(file, "4 - Appearance", "Custom models", value: true, "Whether the two tyrispik items use the bundle model, wood texture and icons shipped in the assets folder beside the plugin. Off, they fall back to the vanilla items they are cloned from - a round log and a piece of elder bark - which is also what happens by itself if the assets folder is missing. Purely what this machine draws: it is not synced, a server does not care, and players on the same server can disagree about it. Read once while the game loads, so it needs a restart.", null); ModelScale = BindLocal(file, "4 - Appearance", "Model scale", 0.5f, "How big the shipped model is where it lies on the ground, as a multiplier on the size the model was built at: 1 is a bundle about a metre and a fifth long, 0.5 an armful of kindling, 0.25 a handful. Only the look changes - weight, stack size and the collider you walk into are untouched. Local, like the setting above. Takes effect without a restart, but tyrispik already lying on the ground keeps the size it was dropped at.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 3f)); CoreWoodPerBatch.SettingChanged += OnSettingChanged; ResinPerBatch.SettingChanged += OnSettingChanged; TarPerBatch.SettingChanged += OnSettingChanged; CoalPerBatch.SettingChanged += OnSettingChanged; ModelScale.SettingChanged += OnSettingChanged; } private void OnSettingChanged(object sender, EventArgs e) { this.ValuesChanged?.Invoke(); } private static ConfigEntry<T> Bind<T>(ConfigFile file, string section, string key, T value, string description, AcceptableValueBase acceptableValues) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown return file.Bind<T>(section, key, value, new ConfigDescription(description, acceptableValues, new object[1] { new ConfigurationManagerAttributes { IsAdminOnly = true } })); } private static ConfigEntry<T> BindLocal<T>(ConfigFile file, string section, string key, T value, string description, AcceptableValueBase acceptableValues) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown return file.Bind<T>(section, key, value, new ConfigDescription(description, acceptableValues, new object[1] { new ConfigurationManagerAttributes { IsAdminOnly = false } })); } } internal static class ModLocalization { public const string SpikName = "$td_tyrispik"; public const string SpikDescription = "$td_tyrispik_desc"; public const string DriedName = "$td_tyrispik_dried"; public const string DriedDescription = "$td_tyrispik_dried_desc"; public static void Register() { CustomLocalization localization = LocalizationManager.Instance.GetLocalization(); string text = "English"; localization.AddTranslation(ref text, new Dictionary<string, string> { { "td_tyrispik", "Tyrispik" }, { "td_tyrispik_desc", "Pitch-soaked heartwood from a pine stump that has stood rotting for ten winters or more, cleaned and split fine into spik. Still raw with sap and water - it must be dried before it will give up its tar." }, { "td_tyrispik_dried", "Dried Tyrispik" }, { "td_tyrispik_dried_desc", "Split tyri, dried hard. Stack it in a covered mile and choke the air, and the tar sweats out of the wood - leaving good charcoal behind." } }); text = "Norwegian"; localization.AddTranslation(ref text, new Dictionary<string, string> { { "td_tyrispik", "Tyrispik" }, { "td_tyrispik_desc", "Kvaerik kjerneved fra en furustubbe som har stått og rotnet i ti vintre eller mer, renset og finkløyvd til spik. Ennå rå av sevje og vann - den må tørkes før den gir fra seg tjære." }, { "td_tyrispik_dried", "Tørket tyrispik" }, { "td_tyrispik_dried_desc", "Finkløyvd tyri, tørket hard. Stables i en tildekket mile med lite luft, så siver tjæra ut av veden - og etterlater god trekull." } }); } } [HarmonyPatch(typeof(ObjectDB), "Awake")] internal static class ObjectDbFallbackPatch { [HarmonyPriority(800)] private static void Prefix() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) Scene activeScene = SceneManager.GetActiveScene(); if (!(((Scene)(ref activeScene)).name != "main")) { TarDistillationPlugin.EnsureContent(); } } } internal static class ObjMesh { private struct Corner { public int Position; public int Uv; public int Normal; public static Corner Parse(string token, int vCount, int vtCount, int vnCount) { string[] parts = token.Split(new char[1] { '/' }); return new Corner { Position = Index(parts, 0, vCount), Uv = Index(parts, 1, vtCount), Normal = Index(parts, 2, vnCount) }; } private static int Index(string[] parts, int slot, int count) { if (slot >= parts.Length || parts[slot].Length == 0) { return -1; } int num = int.Parse(parts[slot], CultureInfo.InvariantCulture); if (num >= 0) { return num - 1; } return count + num; } } private const float SmoothingAngle = 60f; private static readonly char[] Whitespace = new char[2] { ' ', '\t' }; public static Mesh Load(string path, string name) { //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) List<Vector3> list = new List<Vector3>(); List<Vector2> list2 = new List<Vector2>(); List<Vector3> list3 = new List<Vector3>(); List<Corner> list4 = new List<Corner>(); foreach (string item in File.ReadLines(path)) { string text = item.Trim(); if (text.Length != 0 && text[0] != '#') { string[] array = text.Split(Whitespace, StringSplitOptions.RemoveEmptyEntries); switch (array[0]) { case "v": list.Add(new Vector3(Num(array, 1), Num(array, 2), 0f - Num(array, 3))); break; case "vt": list2.Add(new Vector2(Num(array, 1), Num(array, 2))); break; case "vn": list3.Add(new Vector3(Num(array, 1), Num(array, 2), 0f - Num(array, 3))); break; case "f": AddFace(array, list.Count, list2.Count, list3.Count, list4); break; } } } if (list4.Count == 0) { throw new InvalidDataException(Path.GetFileName(path) + " holds no faces"); } return Build(name, list4, list, list2, list3); } private static void AddFace(string[] fields, int vCount, int vtCount, int vnCount, List<Corner> corners) { for (int i = 2; i < fields.Length - 1; i++) { corners.Add(Corner.Parse(fields[1], vCount, vtCount, vnCount)); corners.Add(Corner.Parse(fields[i], vCount, vtCount, vnCount)); corners.Add(Corner.Parse(fields[i + 1], vCount, vtCount, vnCount)); } } private static Mesh Build(string name, List<Corner> corners, List<Vector3> positions, List<Vector2> uvs, List<Vector3> normals) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Expected O, but got Unknown //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) Bounds val = default(Bounds); ((Bounds)(ref val))..ctor(positions[corners[0].Position], Vector3.zero); foreach (Corner corner2 in corners) { ((Bounds)(ref val)).Encapsulate(positions[corner2.Position]); } Vector3 center = ((Bounds)(ref val)).center; int num = corners.Count - corners.Count % 3; Vector3[] array = (Vector3[])(object)new Vector3[num]; Vector2[] array2 = (Vector2[])(object)new Vector2[num]; int[] array3 = new int[num]; for (int i = 0; i < num; i++) { Corner corner = corners[i]; array[i] = positions[corner.Position] - center; array2[i] = ((corner.Uv >= 0 && corner.Uv < uvs.Count) ? uvs[corner.Uv] : Vector2.zero); array3[i] = i; } Mesh val2 = new Mesh { name = name, vertices = array, uv = array2, triangles = array3, normals = Normals(corners, array, normals) }; val2.RecalculateBounds(); val2.RecalculateTangents(); return val2; } private static Vector3[] Normals(List<Corner> corners, Vector3[] vertices, List<Vector3> fileNormals) { //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_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_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_01af: Unknown result type (might be due to invalid IL or missing references) //IL_01b1: Unknown result type (might be due to invalid IL or missing references) //IL_01c6: Unknown result type (might be due to invalid IL or missing references) //IL_01bf: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) int num = vertices.Length; Vector3[] array = (Vector3[])(object)new Vector3[num]; Vector3 val2; if (fileNormals.Count > 0) { for (int i = 0; i < num; i++) { int normal = corners[i].Normal; int num2 = i; Vector3 val; if (normal < 0 || normal >= fileNormals.Count) { val = Vector3.up; } else { val2 = fileNormals[normal]; val = ((Vector3)(ref val2)).normalized; } array[num2] = val; } return array; } Vector3[] array2 = (Vector3[])(object)new Vector3[num / 3]; for (int j = 0; j < array2.Length; j++) { Vector3 val3 = vertices[j * 3]; Vector3 val4 = vertices[j * 3 + 1]; Vector3 val5 = vertices[j * 3 + 2]; int num3 = j; val2 = Vector3.Cross(val4 - val3, val5 - val3); array2[num3] = ((Vector3)(ref val2)).normalized; } Dictionary<int, List<int>> dictionary = new Dictionary<int, List<int>>(); for (int k = 0; k < num; k++) { if (!dictionary.TryGetValue(corners[k].Position, out var value)) { value = new List<int>(); dictionary[corners[k].Position] = value; } value.Add(k / 3); } float num4 = Mathf.Cos((float)Math.PI / 3f); for (int l = 0; l < num; l++) { Vector3 val6 = array2[l / 3]; Vector3 val7 = Vector3.zero; foreach (int item in dictionary[corners[l].Position]) { if (Vector3.Dot(val6, array2[item]) >= num4) { val7 += array2[item]; } } array[l] = ((val7 == Vector3.zero) ? val6 : ((Vector3)(ref val7)).normalized); } return array; } private static float Num(string[] fields, int index) { if (index >= fields.Length) { return 0f; } return float.Parse(fields[index], NumberStyles.Float, CultureInfo.InvariantCulture); } } [HarmonyPatch(typeof(Smelter), "UpdateSmelter")] internal static class SmelterTimePatch { private static readonly Func<Smelter, string> GetQueuedOre = AccessTools.MethodDelegate<Func<Smelter, string>>(AccessTools.Method(typeof(Smelter), "GetQueuedOre", (Type[])null, (Type[])null), (object)null, true); private static void Prefix(Smelter __instance, out float __state) { __state = __instance.m_secPerProduct; int num = TarDistillationPlugin.Cfg?.DryingSeconds.Value ?? 0; if (num > 0 && !(GetQueuedOre(__instance) != "Tyrispik")) { __instance.m_secPerProduct = num; } } private static void Postfix(Smelter __instance, float __state) { __instance.m_secPerProduct = __state; } } [BepInPlugin("hakon.valheim.tardistillation", "TarDistillation", "0.0.4")] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] internal class TarDistillationPlugin : BaseUnityPlugin { public const string PluginGuid = "hakon.valheim.tardistillation"; public const string PluginName = "TarDistillation"; public const string PluginVersion = "0.0.4"; public const string SpikPrefab = "Tyrispik"; public const string DriedSpikPrefab = "TyrispikDried"; private const string CoreWoodPrefab = "RoundLog"; private const string ResinPrefab = "Resin"; private const string ElderBarkPrefab = "ElderBark"; private const string TarPrefab = "Tar"; private static bool contentCreated; private Harmony harmony; internal static ModConfig Cfg { get; private set; } private void Awake() { //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Expected O, but got Unknown Cfg = new ModConfig(((BaseUnityPlugin)this).Config); ModLocalization.Register(); PrefabManager.OnVanillaPrefabsAvailable += AddContent; Cfg.ValuesChanged += ApplyLiveSettings; SynchronizationManager.OnConfigurationSynchronized += delegate { ApplyLiveSettings(); }; harmony = new Harmony("hakon.valheim.tardistillation"); harmony.PatchAll(); } private void OnDestroy() { Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } } private void AddContent() { PrefabManager.OnVanillaPrefabsAvailable -= AddContent; EnsureContent(); } internal static void EnsureContent() { if (contentCreated || Cfg == null || (Object)(object)PrefabManager.Instance.GetPrefab("RoundLog") == (Object)null) { return; } contentCreated = true; try { AddSpik(); AddDriedSpik(); AddConversions(); Logger.LogInfo((object)($"Tar chain: {Cfg.CoreWoodPerBatch.Value} core wood + {Cfg.ResinPerBatch.Value} resin " + "to one spik, dried in " + Smelters.GetInternalName(Cfg.DryingStation.Value) + ", " + $"fermented into {Cfg.TarPerBatch.Value} tar and {Cfg.CoalPerBatch.Value} coal")); } catch (Exception arg) { Logger.LogError((object)$"Could not register the tar chain: {arg}"); } } private static void AddSpik() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Expected O, but got Unknown //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Expected O, but got Unknown //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Expected O, but got Unknown List<RequirementConfig> list = new List<RequirementConfig> { new RequirementConfig { Item = "RoundLog", Amount = Cfg.CoreWoodPerBatch.Value } }; if (Cfg.ResinPerBatch.Value > 0) { list.Add(new RequirementConfig { Item = "Resin", Amount = Cfg.ResinPerBatch.Value }); } CustomItem val = new CustomItem("Tyrispik", "RoundLog", new ItemConfig { Name = "$td_tyrispik", Description = "$td_tyrispik_desc", Amount = 1, Weight = 4f, StackSize = 50, CraftingStation = CraftingStations.GetInternalName(Cfg.SplittingStation.Value), Requirements = list.ToArray() }); ItemVisuals.Apply(val.ItemPrefab, val.ItemDrop.m_itemData.m_shared, "Tyrispik"); ItemManager.Instance.AddItem(val); } private static void AddDriedSpik() { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown CustomItem val = new CustomItem("TyrispikDried", "ElderBark"); SharedData shared = val.ItemDrop.m_itemData.m_shared; shared.m_name = "$td_tyrispik_dried"; shared.m_description = "$td_tyrispik_dried_desc"; shared.m_weight = 3f; shared.m_maxStackSize = 50; ItemVisuals.Apply(val.ItemPrefab, shared, "TyrispikDried"); ItemManager.Instance.AddItem(val); } private static void AddConversions() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Expected O, but got Unknown //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Expected O, but got Unknown //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Expected O, but got Unknown ItemManager.Instance.AddItemConversion(new CustomItemConversion((ConversionConfig)new SmelterConversionConfig { Station = Smelters.GetInternalName(Cfg.DryingStation.Value), FromItem = "Tyrispik", ToItem = "TyrispikDried" })); ItemManager.Instance.AddItemConversion(new CustomItemConversion((ConversionConfig)new FermenterConversionConfig { Station = Fermenters.Fermenter, FromItem = "TyrispikDried", ToItem = "Tar", ProducedItems = Cfg.TarPerBatch.Value })); } private static void ApplyLiveSettings() { UpdateRecipe(); UpdateFermenterYield(); ItemVisuals.ApplyScale(); } private static void UpdateRecipe() { ObjectDB instance = ObjectDB.instance; if ((Object)(object)instance == (Object)null || instance.m_recipes == null) { return; } foreach (Recipe recipe in instance.m_recipes) { if ((Object)(object)recipe == (Object)null || (Object)(object)recipe.m_item == (Object)null || ((Object)recipe.m_item).name != "Tyrispik") { continue; } Requirement[] resources = recipe.m_resources; foreach (Requirement val in resources) { if (!((Object)(object)val?.m_resItem == (Object)null)) { if (((Object)val.m_resItem).name == "RoundLog") { val.m_amount = Cfg.CoreWoodPerBatch.Value; } else if (((Object)val.m_resItem).name == "Resin") { val.m_amount = Cfg.ResinPerBatch.Value; } } } } } private static void UpdateFermenterYield() { ZNetScene instance = ZNetScene.instance; if ((Object)(object)instance == (Object)null) { return; } GameObject prefab = instance.GetPrefab(Fermenters.Fermenter); Fermenter val = (((Object)(object)prefab == (Object)null) ? null : prefab.GetComponent<Fermenter>()); if (val?.m_conversion == null) { return; } foreach (ItemConversion item in val.m_conversion) { if (!((Object)(object)item?.m_from == (Object)null) && !(((Object)item.m_from).name != "TyrispikDried")) { item.m_producedItems = Cfg.TarPerBatch.Value; } } } } }