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 AdvancedPortals v1.2.0
plugins/AdvancedPortals.dll
Decompiled a week ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using Common; using HarmonyLib; using JetBrains.Annotations; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Extensions; using Jotunn.Managers; using Jotunn.Utils; using SimpleJson; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("AdvancedPortals")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Randy Knapp Mods")] [assembly: AssemblyProduct("AdvancedPortals")] [assembly: AssemblyCopyright("Copyright © Randy Knapp 2023")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("0ddde55c-5daf-4b53-b5e2-83b5c44c4682")] [assembly: AssemblyFileVersion("1.2.0")] [assembly: IgnoresAccessChecksTo("assembly_guiutils")] [assembly: IgnoresAccessChecksTo("assembly_utils")] [assembly: IgnoresAccessChecksTo("assembly_valheim")] [assembly: IgnoresAccessChecksTo("Splatform")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.2.0.0")] [module: UnverifiableCode] public static class PlayerExtensions { public static ZDO GetZDO(this Player player) { return ((Character)player).m_nview.GetZDO(); } } namespace Common { public class ConfigPositionedElement : MonoBehaviour { public ConfigEntry<TextAnchor> AnchorConfig; public ConfigEntry<Vector2> PositionConfig; protected RectTransform _rt; protected TextAnchor _currentAnchor; public virtual void Awake() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown _rt = (RectTransform)((Component)this).transform; EnsureCorrectPosition(); } public virtual void Update() { EnsureCorrectPosition(); } public virtual void EnsureCorrectPosition() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0053: 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_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Expected I4, but got Unknown //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: 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_0123: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_012b: 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_015f: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_016d: 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_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Unknown result type (might be due to invalid IL or missing references) //IL_01d7: Unknown result type (might be due to invalid IL or missing references) //IL_01dd: Unknown result type (might be due to invalid IL or missing references) //IL_01de: Unknown result type (might be due to invalid IL or missing references) //IL_01df: Unknown result type (might be due to invalid IL or missing references) //IL_01e5: Unknown result type (might be due to invalid IL or missing references) //IL_0213: Unknown result type (might be due to invalid IL or missing references) //IL_0219: Unknown result type (might be due to invalid IL or missing references) //IL_021a: Unknown result type (might be due to invalid IL or missing references) //IL_021b: Unknown result type (might be due to invalid IL or missing references) //IL_0221: Unknown result type (might be due to invalid IL or missing references) //IL_024c: Unknown result type (might be due to invalid IL or missing references) //IL_0252: Unknown result type (might be due to invalid IL or missing references) //IL_0253: Unknown result type (might be due to invalid IL or missing references) //IL_0254: Unknown result type (might be due to invalid IL or missing references) //IL_025a: Unknown result type (might be due to invalid IL or missing references) //IL_0285: Unknown result type (might be due to invalid IL or missing references) //IL_028b: Unknown result type (might be due to invalid IL or missing references) //IL_028c: Unknown result type (might be due to invalid IL or missing references) //IL_028d: Unknown result type (might be due to invalid IL or missing references) //IL_0293: Unknown result type (might be due to invalid IL or missing references) //IL_02a5: Unknown result type (might be due to invalid IL or missing references) if (AnchorConfig != null && PositionConfig != null && (_currentAnchor != AnchorConfig.Value || !(_rt.anchoredPosition == PositionConfig.Value))) { _currentAnchor = AnchorConfig.Value; TextAnchor currentAnchor = _currentAnchor; Vector2 val = default(Vector2); switch ((int)currentAnchor) { case 0: { RectTransform rt25 = _rt; RectTransform rt26 = _rt; RectTransform rt27 = _rt; ((Vector2)(ref val))..ctor(0f, 1f); rt27.anchorMax = val; Vector2 pivot = (rt26.anchorMin = val); rt25.pivot = pivot; break; } case 1: { RectTransform rt22 = _rt; RectTransform rt23 = _rt; RectTransform rt24 = _rt; ((Vector2)(ref val))..ctor(0.5f, 1f); rt24.anchorMax = val; Vector2 pivot = (rt23.anchorMin = val); rt22.pivot = pivot; break; } case 2: { RectTransform rt19 = _rt; RectTransform rt20 = _rt; RectTransform rt21 = _rt; ((Vector2)(ref val))..ctor(1f, 1f); rt21.anchorMax = val; Vector2 pivot = (rt20.anchorMin = val); rt19.pivot = pivot; break; } case 3: { RectTransform rt16 = _rt; RectTransform rt17 = _rt; RectTransform rt18 = _rt; ((Vector2)(ref val))..ctor(0f, 0.5f); rt18.anchorMax = val; Vector2 pivot = (rt17.anchorMin = val); rt16.pivot = pivot; break; } case 4: { RectTransform rt13 = _rt; RectTransform rt14 = _rt; RectTransform rt15 = _rt; ((Vector2)(ref val))..ctor(0.5f, 0.5f); rt15.anchorMax = val; Vector2 pivot = (rt14.anchorMin = val); rt13.pivot = pivot; break; } case 5: { RectTransform rt10 = _rt; RectTransform rt11 = _rt; RectTransform rt12 = _rt; ((Vector2)(ref val))..ctor(1f, 0.5f); rt12.anchorMax = val; Vector2 pivot = (rt11.anchorMin = val); rt10.pivot = pivot; break; } case 6: { RectTransform rt7 = _rt; RectTransform rt8 = _rt; RectTransform rt9 = _rt; ((Vector2)(ref val))..ctor(0f, 0f); rt9.anchorMax = val; Vector2 pivot = (rt8.anchorMin = val); rt7.pivot = pivot; break; } case 7: { RectTransform rt4 = _rt; RectTransform rt5 = _rt; RectTransform rt6 = _rt; ((Vector2)(ref val))..ctor(0.5f, 0f); rt6.anchorMax = val; Vector2 pivot = (rt5.anchorMin = val); rt4.pivot = pivot; break; } case 8: { RectTransform rt = _rt; RectTransform rt2 = _rt; RectTransform rt3 = _rt; ((Vector2)(ref val))..ctor(1f, 0f); rt3.anchorMax = val; Vector2 pivot = (rt2.anchorMin = val); rt.pivot = pivot; break; } } _rt.anchoredPosition = PositionConfig.Value; } } } [Serializable] public class RecipeRequirementConfig { public string item = ""; public int amount = 1; } [Serializable] public class RecipeConfig { public string name = ""; public string item = ""; public int amount = 1; public string craftingStation = ""; public int minStationLevel = 1; public bool enabled = true; public string repairStation = ""; public List<RecipeRequirementConfig> resources = new List<RecipeRequirementConfig>(); } [Serializable] public class RecipesConfig { public List<RecipeConfig> recipes = new List<RecipeConfig>(); } public static class GameObjectExtensions { public static RectTransform RectTransform(this GameObject go) { Transform transform = go.transform; return (RectTransform)(object)((transform is RectTransform) ? transform : null); } public static T RequireComponent<T>(this GameObject go) where T : Component { T component = go.GetComponent<T>(); if (!((Object)(object)component == (Object)null)) { return component; } return go.AddComponent<T>(); } } public class GotDestroyed : MonoBehaviour { public void OnDisable() { Debug.LogError((object)("I got destroyed! (" + ((Object)((Component)this).gameObject).name + ")")); Debug.Log((object)Environment.StackTrace); } } public static class AssetBundleLoader { private static readonly List<Stream> _liveStreams = new List<Stream>(); public static AssetBundle LoadFromResources(string filename, Assembly assembly) { if (assembly == null) { throw new ArgumentNullException("assembly"); } string text = assembly.GetName().Name + "." + filename; try { Stream manifestResourceStream = assembly.GetManifestResourceStream(text); if (manifestResourceStream == null) { ModLogger.LogError("Embedded asset bundle '" + text + "' not found in " + assembly.GetName().Name + "."); return null; } AssetBundle val = AssetBundle.LoadFromStream(manifestResourceStream); if ((Object)(object)val == (Object)null) { manifestResourceStream.Dispose(); ModLogger.LogError("Embedded asset bundle '" + text + "' failed to load."); return null; } _liveStreams.Add(manifestResourceStream); return val; } catch (Exception ex) { ModLogger.LogError("Failed to load embedded asset bundle '" + text + "': " + ex.Message); return null; } } public static AssetBundle LoadIntoContext(string filename, Assembly assembly) { AssetBundle val = LoadFromResources(filename, assembly); if ((Object)(object)val != (Object)null) { ModContext.AssetBundle = val; } return val; } } public static class ConfigBinder { private static ConfigFile Cfg => ModContext.Cfg; public static ConfigEntry<bool> BindServerConfig(string category, string key, bool value, string description, AcceptableValueBase acceptableValues = null, bool advanced = false) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected O, but got Unknown //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown return Cfg.Bind<bool>(category, key, value, new ConfigDescription(description, acceptableValues, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true, IsAdvanced = advanced } })); } public static ConfigEntry<int> BindServerConfig(string category, string key, int value, string description, bool advanced = false, int valMin = 0, int valMax = 150) { //IL_001a: 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_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown return Cfg.Bind<int>(category, key, value, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange<int>(valMin, valMax), new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true, IsAdvanced = advanced } })); } public static ConfigEntry<float> BindServerConfig(string category, string key, float value, string description, bool advanced = false, float valMin = 0f, float valMax = 150f) { //IL_001a: 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_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown return Cfg.Bind<float>(category, key, value, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange<float>(valMin, valMax), new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true, IsAdvanced = advanced } })); } public static ConfigEntry<string> BindServerConfig(string category, string key, string value, string description, AcceptableValueList<string> acceptableValues = null, bool advanced = false) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected O, but got Unknown //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown return Cfg.Bind<string>(category, key, value, new ConfigDescription(description, (AcceptableValueBase)(object)acceptableValues, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true, IsAdvanced = advanced } })); } public static ConfigEntry<T> BindServerConfig<T>(string category, string key, T value, string description, AcceptableValueBase acceptableValues, bool advanced = false) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected O, but got Unknown //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown return Cfg.Bind<T>(category, key, value, new ConfigDescription(description, acceptableValues, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true, IsAdvanced = advanced } })); } public static ConfigEntry<T> BindClientConfig<T>(string category, string key, T value, string description, AcceptableValueBase acceptableValues = null, bool advanced = false) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected O, but got Unknown //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown return Cfg.Bind<T>(category, key, value, new ConfigDescription(description, acceptableValues, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = false, IsAdvanced = advanced } })); } public static ConfigEntry<T> BindServerConfigInOrder<T>(string category, string key, T value, string description, AcceptableValueBase acceptableValues = null, bool advanced = false) { //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_0026: Expected O, but got Unknown return ConfigFileExtensions.BindConfigInOrder<T>(Cfg, category, key, value, description, true, true, true, acceptableValues, (Action<ConfigEntryBase>)null, new ConfigurationManagerAttributes { IsAdvanced = advanced }); } public static ConfigEntry<T> BindClientConfigInOrder<T>(string category, string key, T value, string description, AcceptableValueBase acceptableValues = null, bool advanced = false) { //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_0026: Expected O, but got Unknown return ConfigFileExtensions.BindConfigInOrder<T>(Cfg, category, key, value, description, false, true, true, acceptableValues, (Action<ConfigEntryBase>)null, new ConfigurationManagerAttributes { IsAdvanced = advanced }); } } public static class ConfigChangeDebouncer { private static readonly Dictionary<object, Action> pendingActions = new Dictionary<object, Action>(); private static readonly Dictionary<object, float> fireAt = new Dictionary<object, float>(); private static readonly HashSet<object> running = new HashSet<object>(); public static void Schedule(object key, Action action) { float num = ((ModContext.ConfigApplyDelay != null) ? ModContext.ConfigApplyDelay.Value : 0f); if (num <= 0f) { action(); return; } ThreadingHelper instance = ThreadingHelper.Instance; if (!((Object)(object)instance == (Object)null)) { pendingActions[key] = action; fireAt[key] = Time.realtimeSinceStartup + num; if (!running.Contains(key)) { running.Add(key); ((MonoBehaviour)instance).StartCoroutine(Run(key)); } } } private static IEnumerator Run(object key) { float value; while (fireAt.TryGetValue(key, out value) && Time.realtimeSinceStartup < value) { yield return null; } pendingActions.TryGetValue(key, out var value2); pendingActions.Remove(key); fireAt.Remove(key); running.Remove(key); value2?.Invoke(); } } internal static class ConfigDrawHelpers { private static readonly Dictionary<object, string> TextBuffer = new Dictionary<object, string>(); private static readonly Dictionary<object, float> SliderPending = new Dictionary<object, float>(); private static GUIStyle _headerButton; private static GUIStyle _groupLabel; private static GUIStyle _dim; internal static GUIStyle HeaderButton => _headerButton; internal static GUIStyle Dim => _dim; internal static void EnsureStyles() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Expected O, but got Unknown //IL_004f: 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_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Expected O, but got Unknown if (_headerButton == null) { _headerButton = new GUIStyle(GUI.skin.button) { alignment = (TextAnchor)3, fontStyle = (FontStyle)1 }; _groupLabel = new GUIStyle(GUI.skin.label) { fontStyle = (FontStyle)1 }; _dim = new GUIStyle(GUI.skin.label) { fontStyle = (FontStyle)2, fontSize = 11 }; } } internal static ConfigurationManagerAttributes GetAttributes(ConfigEntryBase entry) { if (entry == null) { return null; } ConfigDescription description = entry.Description; if (description == null) { return null; } return description.Tags?.OfType<ConfigurationManagerAttributes>().FirstOrDefault(); } internal static void Hide(ConfigEntryBase entry) { ConfigurationManagerAttributes attributes = GetAttributes(entry); if (attributes != null) { attributes.Browsable = false; } } internal static void GroupHeader(string text) { GUILayout.Space(4f); GUILayout.Label(text, _groupLabel, Array.Empty<GUILayoutOption>()); } private static bool EnterPressed() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Invalid comparison between Unknown and I4 //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Invalid comparison between Unknown and I4 //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Invalid comparison between Unknown and I4 if ((int)Event.current.type == 4) { if ((int)Event.current.keyCode != 13) { return (int)Event.current.keyCode == 271; } return true; } return false; } internal static void DrawBool(string label, ConfigEntry<bool> cfg) { bool flag = GUILayout.Toggle(cfg.Value, " " + label, Array.Empty<GUILayoutOption>()); if (flag != cfg.Value) { cfg.Value = flag; } } internal static void DrawString(string label, ConfigEntry<string> cfg) { GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.Label(label, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(230f) }); string text = "str_" + ((object)cfg).GetHashCode(); GUI.SetNextControlName(text); bool flag = GUI.GetNameOfFocusedControl() == text; string value; string text2 = GUILayout.TextField((flag && TextBuffer.TryGetValue(cfg, out value)) ? value : cfg.Value, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(230f) }); string value2; if (flag) { TextBuffer[cfg] = text2; if (EnterPressed() && cfg.Value != text2) { cfg.Value = text2; } } else if (TextBuffer.TryGetValue(cfg, out value2)) { if (cfg.Value != value2) { cfg.Value = value2; } TextBuffer.Remove(cfg); } GUILayout.EndHorizontal(); } internal static void DrawChoice(string label, ConfigEntry<string> cfg) { GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.Label(label, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(230f) }); if (((ConfigEntryBase)cfg).Description.AcceptableValues is AcceptableValueList<string> val && val.AcceptableValues.Length != 0) { string[] acceptableValues = val.AcceptableValues; int num = Array.IndexOf(acceptableValues, cfg.Value); if (num < 0) { num = 0; } if (GUILayout.Button("◄", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(26f) })) { cfg.Value = acceptableValues[(num - 1 + acceptableValues.Length) % acceptableValues.Length]; } GUILayout.Label(cfg.Value, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(160f) }); if (GUILayout.Button("►", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(26f) })) { cfg.Value = acceptableValues[(num + 1) % acceptableValues.Length]; } } else { GUILayout.Label(cfg.Value, Array.Empty<GUILayoutOption>()); } GUILayout.EndHorizontal(); } internal static void DrawFloat(string label, ConfigEntry<float> cfg) { float num = 0f; float num2 = Mathf.Max(100f, cfg.Value); if (((ConfigEntryBase)cfg).Description.AcceptableValues is AcceptableValueRange<float> val) { num = val.MinValue; num2 = val.MaxValue; } float num3 = DrawSliderRow(label, cfg, cfg.Value, num, num2, isInt: false); if (num3 != cfg.Value) { cfg.Value = Mathf.Clamp(num3, num, num2); } } internal static void DrawInt(string label, ConfigEntry<int> cfg) { float num = 0f; float num2 = Mathf.Max(100f, (float)cfg.Value); if (((ConfigEntryBase)cfg).Description.AcceptableValues is AcceptableValueRange<int> val) { num = val.MinValue; num2 = val.MaxValue; } int num3 = Mathf.Clamp(Mathf.RoundToInt(DrawSliderRow(label, cfg, cfg.Value, num, num2, isInt: true)), (int)num, (int)num2); if (num3 != cfg.Value) { cfg.Value = num3; } } private static float DrawSliderRow(string label, object key, float current, float min, float max, bool isInt) { float num = current; GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.Label(label, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(230f) }); float value; float num2 = (SliderPending.TryGetValue(key, out value) ? value : current); float num3 = GUILayout.HorizontalSlider(num2, min, max, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(150f) }); if (Mathf.Abs(num3 - num2) > Mathf.Epsilon) { SliderPending[key] = num3; } if (SliderPending.TryGetValue(key, out var value2) && !Input.GetMouseButton(0)) { SliderPending.Remove(key); num = value2; } float value3; float num4 = (SliderPending.TryGetValue(key, out value3) ? value3 : num); string text = "num_" + key.GetHashCode(); GUI.SetNextControlName(text); bool flag = GUI.GetNameOfFocusedControl() == text; string text2 = (isInt ? Mathf.RoundToInt(num4).ToString() : num4.ToString("0.###")); string value4; string text3 = GUILayout.TextField((flag && TextBuffer.TryGetValue(key, out value4)) ? value4 : text2, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(70f) }); string value5; if (flag) { TextBuffer[key] = text3; if (EnterPressed() && float.TryParse(text3, out var result)) { num = result; } } else if (TextBuffer.TryGetValue(key, out value5)) { if (float.TryParse(value5, out var result2)) { num = result2; } TextBuffer.Remove(key); } GUILayout.Label("[" + (isInt ? min.ToString() : min.ToString("0.#")) + " - " + (isInt ? max.ToString() : max.ToString("0.#")) + "]", _dim, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(90f) }); GUILayout.EndHorizontal(); return num; } } internal static class ItemConfigDrawer { private static readonly Dictionary<string, bool> Expanded = new Dictionary<string, bool>(); private static readonly Dictionary<object, List<string[]>> RecipeRows = new Dictionary<object, List<string[]>>(); private static int _order = 0; private static readonly KeyValuePair<string, ItemStat[]>[] StatGroups = new KeyValuePair<string, ItemStat[]>[5] { new KeyValuePair<string, ItemStat[]>("Damage", new ItemStat[20] { ItemStat.slash, ItemStat.slash_per_level, ItemStat.blunt, ItemStat.blunt_per_level, ItemStat.pierce, ItemStat.pierce_per_level, ItemStat.fire, ItemStat.fire_per_level, ItemStat.lightning, ItemStat.lightning_per_level, ItemStat.frost, ItemStat.frost_per_level, ItemStat.poison, ItemStat.poison_per_level, ItemStat.spirit, ItemStat.spirit_per_level, ItemStat.pickaxe, ItemStat.pickaxe_per_level, ItemStat.chop, ItemStat.chop_per_level }), new KeyValuePair<string, ItemStat[]>("Combat", new ItemStat[20] { ItemStat.attack_force, ItemStat.primary_attack_force_multiply, ItemStat.secondary_attack_force_multiply, ItemStat.primary_attack_stamina, ItemStat.primary_attack_eitr, ItemStat.primary_attack_flat_health_cost, ItemStat.primary_attack_percent_health_cost, ItemStat.primary_attack_health_returned, ItemStat.primary_attack_damage_bonus_per_missing_hp, ItemStat.primary_attack_projectile_count, ItemStat.secondary_attack_stamina, ItemStat.secondary_attack_eitr, ItemStat.secondary_attack_flat_health_cost, ItemStat.secondary_attack_percent_health_cost, ItemStat.projectile_velocity, ItemStat.projectile_accuracy_max, ItemStat.bow_draw_speed, ItemStat.crossbow_reload_speed, ItemStat.crossbow_reload_stamina_drain, ItemStat.draw_stamina_drain }), new KeyValuePair<string, ItemStat[]>("Defense", new ItemStat[5] { ItemStat.block_armor, ItemStat.block_armor_per_level, ItemStat.parry, ItemStat.block_force, ItemStat.block_force_per_level }), new KeyValuePair<string, ItemStat[]>("Item", new ItemStat[6] { ItemStat.durability, ItemStat.durability_per_level, ItemStat.max_item_level, ItemStat.tool_level, ItemStat.movement_speed, ItemStat.amount }), new KeyValuePair<string, ItemStat[]>("Food", new ItemStat[5] { ItemStat.food_health, ItemStat.food_stamina, ItemStat.food_eitr, ItemStat.food_regen, ItemStat.food_duration }) }; internal static void Attach(ItemDefinition itemdef) { ConfigDrawHelpers.Hide((ConfigEntryBase)(object)itemdef.StationLVLCfg); ConfigDrawHelpers.Hide((ConfigEntryBase)(object)itemdef.CraftAmountCfg); ConfigDrawHelpers.Hide((ConfigEntryBase)(object)itemdef.CraftedAtCfg); ConfigDrawHelpers.Hide((ConfigEntryBase)(object)itemdef.Recipe.RecipeConfig); if (itemdef.ModifableStats != null) { foreach (ItemStatConfig value in itemdef.ModifableStats.Values) { if (value.Cfg != null) { ConfigDrawHelpers.Hide((ConfigEntryBase)(object)value.Cfg); } if (value.CfgInt != null) { ConfigDrawHelpers.Hide((ConfigEntryBase)(object)value.CfgInt); } } } if (itemdef.DamageMods != null) { foreach (HitCustomDamageMod value2 in itemdef.DamageMods.Values) { if (value2.DmgModCfg != null) { ConfigDrawHelpers.Hide((ConfigEntryBase)(object)value2.DmgModCfg); } } } ConfigurationManagerAttributes attributes = ConfigDrawHelpers.GetAttributes((ConfigEntryBase)(object)itemdef.CraftableCfg); if (attributes != null) { attributes.CustomDrawer = delegate { Draw(itemdef); }; attributes.HideSettingName = true; attributes.HideDefaultButton = true; attributes.Category = itemdef.Category.ToString(); attributes.Order = _order--; } } private static void Draw(ItemDefinition itemdef) { //IL_02b1: Unknown result type (might be due to invalid IL or missing references) //IL_02b6: Unknown result type (might be due to invalid IL or missing references) ConfigDrawHelpers.EnsureStyles(); GUILayout.BeginVertical(GUI.skin.box, Array.Empty<GUILayoutOption>()); bool value; bool flag = Expanded.TryGetValue(itemdef.DisplayName, out value) && value; if (GUILayout.Button((flag ? "▾ " : "▸ ") + itemdef.Name, ConfigDrawHelpers.HeaderButton, Array.Empty<GUILayoutOption>())) { flag = !flag; Expanded[itemdef.DisplayName] = flag; } if (flag) { int num; if (SynchronizationManager.Instance != null) { num = (SynchronizationManager.Instance.PlayerIsAdmin ? 1 : 0); if (num == 0) { GUILayout.Label("Server-controlled – admin only.", ConfigDrawHelpers.Dim, Array.Empty<GUILayoutOption>()); } } else { num = 1; } bool enabled = GUI.enabled; GUI.enabled = (byte)num != 0; ConfigDrawHelpers.GroupHeader("Crafting"); ConfigDrawHelpers.DrawBool("Craftable", itemdef.CraftableCfg); ConfigDrawHelpers.DrawString("Crafted at", itemdef.CraftedAtCfg); ConfigDrawHelpers.DrawInt("Station level", itemdef.StationLVLCfg); ConfigDrawHelpers.DrawInt("Craft amount", itemdef.CraftAmountCfg); DrawRecipeEditor(itemdef); HashSet<ItemStat> drawn = new HashSet<ItemStat>(); KeyValuePair<string, ItemStat[]>[] statGroups = StatGroups; for (int i = 0; i < statGroups.Length; i++) { KeyValuePair<string, ItemStat[]> keyValuePair = statGroups[i]; List<ItemStat> list = keyValuePair.Value.Where((ItemStat s) => IsConfigurable(itemdef, s)).ToList(); bool flag2 = keyValuePair.Key == "Damage" && itemdef.DamageMods != null && itemdef.DamageMods.Count > 0; if (list.Count == 0 && !flag2) { continue; } ConfigDrawHelpers.GroupHeader(keyValuePair.Key); foreach (ItemStat item in list) { DrawStat(itemdef, item); drawn.Add(item); } if (!flag2) { continue; } foreach (KeyValuePair<DamageType, HitCustomDamageMod> damageMod in itemdef.DamageMods) { if (damageMod.Value.Configurable && damageMod.Value.DmgModCfg != null) { ConfigDrawHelpers.DrawChoice(((object)damageMod.Key/*cast due to .constrained prefix*/).ToString() + " resistance", damageMod.Value.DmgModCfg); } } } if (itemdef.ModifableStats != null) { List<ItemStat> list2 = itemdef.ModifableStats.Keys.Where((ItemStat s) => !drawn.Contains(s) && IsConfigurable(itemdef, s)).ToList(); if (list2.Count > 0) { ConfigDrawHelpers.GroupHeader("Other"); foreach (ItemStat item2 in list2) { DrawStat(itemdef, item2); } } } GUI.enabled = enabled; } GUILayout.EndVertical(); } private static bool IsConfigurable(ItemDefinition itemdef, ItemStat s) { if (itemdef.ModifableStats != null && itemdef.ModifableStats.TryGetValue(s, out var value)) { return value.Configurable; } return false; } private static void DrawStat(ItemDefinition itemdef, ItemStat s) { ItemStatConfig itemStatConfig = itemdef.ModifableStats[s]; string label = s.ToString().Replace('_', ' '); if (itemStatConfig.IsInt) { ConfigDrawHelpers.DrawInt(label, itemStatConfig.CfgInt); } else { ConfigDrawHelpers.DrawFloat(label, itemStatConfig.Cfg); } } private static void DrawRecipeEditor(ItemDefinition itemdef) { ConfigEntry<string> recipeConfig = itemdef.Recipe.RecipeConfig; ConfigDrawHelpers.GroupHeader("Recipe"); if (!RecipeRows.TryGetValue(recipeConfig, out var value)) { value = ParseCsv(recipeConfig.Value, 3); RecipeRows[recipeConfig] = value; } GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.Label("Resource (prefab)", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(200f) }); GUILayout.Label("Amount", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(60f) }); GUILayout.Label("Per level", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(70f) }); GUILayout.EndHorizontal(); for (int i = 0; i < value.Count; i++) { string[] array = value[i]; GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); array[0] = GUILayout.TextField(array[0] ?? "", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(200f) }); array[1] = DigitsOnly(GUILayout.TextField(array[1] ?? "", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(60f) })); array[2] = DigitsOnly(GUILayout.TextField(array[2] ?? "", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(70f) })); bool num = GUILayout.Button("✕", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(26f) }); GUILayout.EndHorizontal(); if (num) { value.RemoveAt(i); i--; } } GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); if (GUILayout.Button("Add resource", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(120f) })) { value.Add(new string[3] { "", "1", "0" }); } if (GUILayout.Button("Apply", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(80f) })) { recipeConfig.Value = SerializeCsv(value); } if (GUILayout.Button("Reload", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(80f) })) { RecipeRows[recipeConfig] = ParseCsv(recipeConfig.Value, 3); } GUILayout.EndHorizontal(); GUILayout.Label("Applied: " + recipeConfig.Value, ConfigDrawHelpers.Dim, Array.Empty<GUILayoutOption>()); } internal static List<string[]> ParseCsv(string csv, int cols) { List<string[]> list = new List<string[]>(); string[] array = (csv ?? "").Split(new char[1] { '|' }); foreach (string text in array) { if (!string.IsNullOrEmpty(text) && text.Trim().Length != 0) { string[] array2 = text.Split(new char[1] { ',' }); string[] array3 = new string[cols]; for (int j = 0; j < cols; j++) { array3[j] = ((j < array2.Length) ? array2[j] : ""); } list.Add(array3); } } return list; } internal static string SerializeCsv(List<string[]> rows) { return string.Join("|", (from r in rows where !string.IsNullOrEmpty(r[0]) && r[0].Trim().Length > 0 select string.Join(",", r)).ToArray()); } internal static string DigitsOnly(string s) { return new string((s ?? "").Where((char ch) => char.IsDigit(ch) || ch == '-').ToArray()); } } internal static class PieceConfigDrawer { private static readonly Dictionary<string, bool> Expanded = new Dictionary<string, bool>(); private static readonly Dictionary<object, List<string[]>> CostRows = new Dictionary<object, List<string[]>>(); private static int _order = 0; internal static void Attach(PieceLoader.BuildPiece jp) { ConfigDrawHelpers.Hide((ConfigEntryBase)(object)jp.Cfgs.RequiresWorkbench); ConfigDrawHelpers.Hide((ConfigEntryBase)(object)jp.Cfgs.Workbench); ConfigDrawHelpers.Hide((ConfigEntryBase)(object)jp.Cfgs.PieceCategory); ConfigDrawHelpers.Hide((ConfigEntryBase)(object)jp.Cfgs.PieceCost); ConfigurationManagerAttributes attributes = ConfigDrawHelpers.GetAttributes((ConfigEntryBase)(object)jp.Cfgs.Enabled); if (attributes != null) { attributes.CustomDrawer = delegate { Draw(jp); }; attributes.HideSettingName = true; attributes.HideDefaultButton = true; attributes.Category = "Building Pieces"; attributes.Order = _order--; } } private static void Draw(PieceLoader.BuildPiece jp) { ConfigDrawHelpers.EnsureStyles(); GUILayout.BeginVertical(GUI.skin.box, Array.Empty<GUILayoutOption>()); bool value; bool flag = Expanded.TryGetValue(jp.Name, out value) && value; if (GUILayout.Button((flag ? "▾ " : "▸ ") + jp.Name, ConfigDrawHelpers.HeaderButton, Array.Empty<GUILayoutOption>())) { flag = !flag; Expanded[jp.Name] = flag; } if (flag) { int num; if (SynchronizationManager.Instance != null) { num = (SynchronizationManager.Instance.PlayerIsAdmin ? 1 : 0); if (num == 0) { GUILayout.Label("Server-controlled – admin only.", ConfigDrawHelpers.Dim, Array.Empty<GUILayoutOption>()); } } else { num = 1; } bool enabled = GUI.enabled; GUI.enabled = (byte)num != 0; ConfigDrawHelpers.GroupHeader("Settings"); ConfigDrawHelpers.DrawBool("Enabled", jp.Cfgs.Enabled); ConfigDrawHelpers.DrawBool("Requires workbench", jp.Cfgs.RequiresWorkbench); ConfigDrawHelpers.DrawString("Workbench", jp.Cfgs.Workbench); ConfigDrawHelpers.DrawChoice("Piece category", jp.Cfgs.PieceCategory); DrawCostEditor(jp); GUI.enabled = enabled; } GUILayout.EndVertical(); } private static void DrawCostEditor(PieceLoader.BuildPiece jp) { ConfigEntry<string> pieceCost = jp.Cfgs.PieceCost; ConfigDrawHelpers.GroupHeader("Building Cost"); if (!CostRows.TryGetValue(pieceCost, out var value)) { value = ItemConfigDrawer.ParseCsv(pieceCost.Value, 3); CostRows[pieceCost] = value; } GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.Label("Resource (prefab)", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(200f) }); GUILayout.Label("Amount", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(60f) }); GUILayout.Label("Refund", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(90f) }); GUILayout.EndHorizontal(); for (int i = 0; i < value.Count; i++) { string[] array = value[i]; GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); array[0] = GUILayout.TextField(array[0] ?? "", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(200f) }); array[1] = ItemConfigDrawer.DigitsOnly(GUILayout.TextField(array[1] ?? "", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(60f) })); bool num = (array[2] ?? "").Trim().ToLower() != "false"; bool flag = GUILayout.Toggle(num, num ? " refundable" : " no refund", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(110f) }); array[2] = (flag ? "true" : "false"); bool num2 = GUILayout.Button("✕", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(26f) }); GUILayout.EndHorizontal(); if (num2) { value.RemoveAt(i); i--; } } GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); if (GUILayout.Button("Add resource", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(120f) })) { value.Add(new string[3] { "", "1", "true" }); } if (GUILayout.Button("Apply", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(80f) })) { pieceCost.Value = ItemConfigDrawer.SerializeCsv(value); } if (GUILayout.Button("Reload", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(80f) })) { CostRows[pieceCost] = ItemConfigDrawer.ParseCsv(pieceCost.Value, 3); } GUILayout.EndHorizontal(); GUILayout.Label("Applied: " + pieceCost.Value, ConfigDrawHelpers.Dim, Array.Empty<GUILayoutOption>()); } } public class ItemBatchLoader { internal static List<ItemDefinition> resourceDefinitions = new List<ItemDefinition>(); internal static AssetBundle Assets; internal static Dictionary<string, string> AddedItems = new Dictionary<string, string>(); internal static List<string> ArcheryAmmoToAdd = new List<string>(); public static string PrefabPathFormat = "Assets/Custom/Weapons/{0}/{1}.prefab"; public static string IconPathFormat = "Assets/Custom/Icons/{0}.png"; public static bool FixReferences = true; private static readonly List<KeyValuePair<string, Action<ItemData>>> pendingWorldUpdates = new List<KeyValuePair<string, Action<ItemData>>>(); private static bool worldUpdateScheduled = false; internal static readonly AcceptableValueList<string> allowedModifiers = new AcceptableValueList<string>(new string[6] { ((object)(DamageModifier)0/*cast due to .constrained prefix*/).ToString(), ((object)(DamageModifier)6/*cast due to .constrained prefix*/).ToString(), ((object)(DamageModifier)2/*cast due to .constrained prefix*/).ToString(), ((object)(DamageModifier)1/*cast due to .constrained prefix*/).ToString(), ((object)(DamageModifier)5/*cast due to .constrained prefix*/).ToString(), ((object)(DamageModifier)3/*cast due to .constrained prefix*/).ToString() }); public bool AddDefinition(ItemDefinition itemdef) { resourceDefinitions.Add(itemdef); return true; } public bool BatchSetup(AssetBundle assetBundle = null, bool reverse_order = true) { Assets = assetBundle ?? ModContext.AssetBundle; if ((Object)(object)Assets == (Object)null) { ModLogger.LogError("No asset bundle available; items will not be registered."); return false; } if (reverse_order) { resourceDefinitions.Reverse(); } ModContext.SaveOnSet(enabled: false); WireConfigDefs(); if (!Utils.IsServer()) { BatchAddItems(); SetupOnChange(); ItemManager.OnItemsRegistered += AddAmmoItemsToArcheryTarget; ItemManager.OnItemsRegistered += ReapplyAllRecipeConfig; SynchronizationManager.OnConfigurationSynchronized += OnModConfigsChanged; } ModContext.SaveOnSet(enabled: true); return true; } private static bool WireConfigDefs() { //IL_0304: Unknown result type (might be due to invalid IL or missing references) //IL_031a: Unknown result type (might be due to invalid IL or missing references) //IL_031f: Unknown result type (might be due to invalid IL or missing references) //IL_0335: Unknown result type (might be due to invalid IL or missing references) foreach (ItemDefinition resourceDefinition in resourceDefinitions) { if (resourceDefinition.Recipe == null) { resourceDefinition.Recipe = new RecipeDefinition(); } if (resourceDefinition.Recipe.RecipeItems == null) { ModLogger.LogError("Item definition '" + resourceDefinition.Name + "' has no recipe items; it will be registered without a crafting recipe."); resourceDefinition.Recipe.RecipeItems = new List<RecipeIngredient>(); } resourceDefinition.DisplayName = string.Join("", resourceDefinition.Name.Split((string[]?)null, StringSplitOptions.RemoveEmptyEntries)); AddedItems.Add(resourceDefinition.DisplayName, resourceDefinition.Prefab); string category = $"{resourceDefinition.Category} - {resourceDefinition.Name}"; resourceDefinition.CraftableCfg = ConfigBinder.BindServerConfig(category, resourceDefinition.DisplayName + "-craftable", resourceDefinition.Craftable, "Enable/Disable the crafting recipe for " + resourceDefinition.Name + "."); resourceDefinition.StationLVLCfg = ConfigBinder.BindServerConfig(category, resourceDefinition.DisplayName + "-stationRequiredLevel", resourceDefinition.ReqStationlevel, "Sets the required minimum crafting station level to craft " + resourceDefinition.Name, advanced: true, 1, 10); resourceDefinition.CraftAmountCfg = ConfigBinder.BindServerConfig(category, resourceDefinition.DisplayName + "-craftAmount", resourceDefinition.CraftAmount, "Sets the amount of " + resourceDefinition.Name + " crafted per recipe.", advanced: true, 1, 50); resourceDefinition.CraftedAtCfg = ConfigBinder.BindServerConfig(category, resourceDefinition.DisplayName + "-craftedAt", resourceDefinition.CraftedAt, "Sets the crafting station for " + resourceDefinition.Name + "."); foreach (KeyValuePair<ItemStat, ItemStatConfig> modifableStat in resourceDefinition.ModifableStats) { if (modifableStat.Value.Configurable) { if (modifableStat.Value.IsInt) { modifableStat.Value.CfgInt = ConfigBinder.BindServerConfig(category, $"{resourceDefinition.DisplayName}-{modifableStat.Key}", (int)modifableStat.Value.Default_value, $"Value for {modifableStat.Key} on {resourceDefinition.Name}", advanced: true, (int)modifableStat.Value.Min, (int)modifableStat.Value.Max); } else { modifableStat.Value.Cfg = ConfigBinder.BindServerConfig(category, $"{resourceDefinition.DisplayName}-{modifableStat.Key}", modifableStat.Value.Default_value, $"Value for {modifableStat.Key} on {resourceDefinition.Name}", advanced: true, modifableStat.Value.Min, modifableStat.Value.Max); } } } if (resourceDefinition.DamageMods != null) { foreach (KeyValuePair<DamageType, HitCustomDamageMod> damageMod in resourceDefinition.DamageMods) { damageMod.Value.DmgModCfg = ConfigBinder.BindServerConfig(category, $"{resourceDefinition.DisplayName}-{damageMod.Key}-DamageModifier", ((object)damageMod.Value.DamageModifier/*cast due to .constrained prefix*/).ToString(), $"Damage modifier for {damageMod.Key} on {resourceDefinition.Name}", allowedModifiers, advanced: true); } } resourceDefinition.Recipe.RecipeConfig = ConfigBinder.BindServerConfig(category, resourceDefinition.DisplayName + "-recipe", BuildStringRecipeFromItemDef(resourceDefinition), "Recipe for " + resourceDefinition.Name + ". Should be in the format of Prefab,Amount,AmountPerLevel|Prefab,Amount,AmountPerLevel eg: Wood,12,2|Stone,2,0"); if (!ValidateRecipeConfig(resourceDefinition)) { BuildRecipeReqsFromDefault(resourceDefinition); } ItemConfigDrawer.Attach(resourceDefinition); } return true; } private bool SetupOnChange() { foreach (ItemDefinition resourceDefinition in resourceDefinitions) { ItemDefinition itemdef = resourceDefinition; itemdef.CraftableCfg.SettingChanged += delegate { ConfigChangeDebouncer.Schedule(itemdef.CraftableCfg, delegate { EnableDisableItemInDB(itemdef, itemdef.CraftableCfg.Value); }); }; itemdef.StationLVLCfg.SettingChanged += delegate { ConfigChangeDebouncer.Schedule(itemdef.StationLVLCfg, delegate { ModifyItemRecipeLevel(itemdef, itemdef.StationLVLCfg.Value); }); }; itemdef.CraftedAtCfg.SettingChanged += delegate { ConfigChangeDebouncer.Schedule(itemdef.CraftedAtCfg, delegate { ModifyItemRecipeCraftedAt(itemdef); }); }; itemdef.CraftAmountCfg.SettingChanged += delegate { ConfigChangeDebouncer.Schedule(itemdef.CraftAmountCfg, delegate { ModifyItemRecipeCraftAmount(itemdef, itemdef.CraftAmountCfg.Value); }); }; foreach (KeyValuePair<ItemStat, ItemStatConfig> modifableStat in itemdef.ModifableStats) { KeyValuePair<ItemStat, ItemStatConfig> stat = modifableStat; object statKey; if (stat.Value.Configurable) { statKey = (stat.Value.IsInt ? ((object)stat.Value.CfgInt) : ((object)stat.Value.Cfg)); if (stat.Value.IsInt) { stat.Value.CfgInt.SettingChanged += UpdateFromConfig; } else { stat.Value.Cfg.SettingChanged += UpdateFromConfig; } } void UpdateFromConfig(object sender, EventArgs args) { ConfigChangeDebouncer.Schedule(statKey, delegate { if (!((Object)(object)ZNet.instance == (Object)null) && ((Behaviour)ZNet.instance).enabled) { stat.Value.Default_value = (stat.Value.IsInt ? ((float)stat.Value.CfgInt.Value) : stat.Value.Cfg.Value); UpdateItemInPlayerInventory(itemdef.Prefab, delegate(ItemData item) { ItemDataConfigModifier(stat.Key, stat.Value.Default_value, item); }); EnqueueWorldUpdate(itemdef.Prefab, delegate(ItemData item) { ItemDataConfigModifier(stat.Key, stat.Value.Default_value, item); }); } }); } } itemdef.Recipe.RecipeConfig.SettingChanged += delegate { ConfigChangeDebouncer.Schedule(itemdef.Recipe.RecipeConfig, delegate { if (ValidateRecipeConfig(itemdef)) { ModifyItemRecipeInODB(itemdef); } }); }; if (itemdef.DamageMods == null) { continue; } foreach (KeyValuePair<DamageType, HitCustomDamageMod> dmgmod in itemdef.DamageMods) { dmgmod.Value.DmgModCfg.SettingChanged += delegate { ConfigChangeDebouncer.Schedule(dmgmod.Value.DmgModCfg, delegate { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)ZNet.instance == (Object)null) && ((Behaviour)ZNet.instance).enabled) { DamageModifier modifier = (DamageModifier)Enum.Parse(typeof(DamageModifier), dmgmod.Value.DmgModCfg.Value); UpdateItemInPlayerInventory(itemdef.Prefab, delegate(ItemData item) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) SetItemDamageModifier(modifier, dmgmod.Key, item); }); EnqueueWorldUpdate(itemdef.Prefab, delegate(ItemData item) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) SetItemDamageModifier(modifier, dmgmod.Key, item); }); } }); }; } } return true; } private static void ReapplyAllRecipeConfig() { if ((Object)(object)ObjectDB.instance == (Object)null || ObjectDB.instance.m_recipes == null) { return; } foreach (ItemDefinition resourceDefinition in resourceDefinitions) { EnsureRecipeInDB(resourceDefinition); if (ValidateRecipeConfig(resourceDefinition)) { ModifyItemRecipeInODB(resourceDefinition); } ModifyItemRecipeLevel(resourceDefinition, resourceDefinition.StationLVLCfg.Value); ModifyItemRecipeCraftedAt(resourceDefinition); ModifyItemRecipeCraftAmount(resourceDefinition, resourceDefinition.CraftAmountCfg.Value); EnableDisableItemInDB(resourceDefinition, resourceDefinition.CraftableCfg.Value); } if ((Object)(object)Player.m_localPlayer != (Object)null) { Player.m_localPlayer.UpdateKnownRecipesList(); } } private static void OnModConfigsChanged(object sender, ConfigurationSynchronizationEventArgs e) { if (e.UpdatedPluginGUIDs == null || e.UpdatedPluginGUIDs.Count <= 0 || e.UpdatedPluginGUIDs.Contains(ModContext.PluginGuid)) { ReapplyAllRecipeConfig(); } } private static T LoadBundleAsset<T>(string pathFormat, string bareName, params object[] formatArgs) where T : Object { if (!string.IsNullOrEmpty(pathFormat)) { T val = Assets.LoadAsset<T>(string.Format(pathFormat, formatArgs)); if ((Object)(object)val != (Object)null) { return val; } } return Assets.LoadAsset<T>(bareName); } private static bool BatchAddItems() { //IL_0259: Unknown result type (might be due to invalid IL or missing references) //IL_0263: Expected O, but got Unknown //IL_0269: Unknown result type (might be due to invalid IL or missing references) //IL_0270: Expected O, but got Unknown //IL_02fc: Unknown result type (might be due to invalid IL or missing references) //IL_0306: Expected O, but got Unknown //IL_01e4: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: Unknown result type (might be due to invalid IL or missing references) foreach (ItemDefinition resourceDefinition in resourceDefinitions) { GameObject val = LoadBundleAsset<GameObject>(PrefabPathFormat, resourceDefinition.Prefab, new object[2] { resourceDefinition.Category, resourceDefinition.Prefab }); if ((Object)(object)val == (Object)null) { ModLogger.LogError("Could not find prefab '" + resourceDefinition.Prefab + "' for " + resourceDefinition.Name + " in the asset bundle; skipping."); continue; } Sprite val2 = (string.IsNullOrEmpty(resourceDefinition.Icon) ? null : LoadBundleAsset<Sprite>(IconPathFormat, resourceDefinition.Icon, new object[1] { resourceDefinition.Icon })); ItemDrop component = val.GetComponent<ItemDrop>(); foreach (KeyValuePair<ItemStat, ItemStatConfig> modifableStat in resourceDefinition.ModifableStats) { if (!modifableStat.Value.Configurable) { ItemDataConfigModifier(modifableStat.Key, modifableStat.Value.Default_value, component.m_itemData); } else if (modifableStat.Value.IsInt) { ItemDataConfigModifier(modifableStat.Key, modifableStat.Value.CfgInt.Value, component.m_itemData); } else { ItemDataConfigModifier(modifableStat.Key, modifableStat.Value.Cfg.Value, component.m_itemData); } } if (resourceDefinition.DamageMods != null) { foreach (KeyValuePair<DamageType, HitCustomDamageMod> damageMod in resourceDefinition.DamageMods) { if (damageMod.Value.Configurable && damageMod.Value.DmgModCfg != null) { SetItemDamageModifier((DamageModifier)Enum.Parse(typeof(DamageModifier), damageMod.Value.DmgModCfg.Value), damageMod.Key, component.m_itemData); } } } if (resourceDefinition.Recipe.RecipeReqs == null || resourceDefinition.Recipe.RecipeReqs.Count == 0) { ModLogger.LogError("Item '" + resourceDefinition.Name + "' has no valid recipe requirements; registering it without a crafting recipe."); ItemManager.Instance.AddItem(new CustomItem(val, FixReferences)); } else { ItemConfig val3 = new ItemConfig(); val3.Amount = resourceDefinition.CraftAmountCfg.Value; val3.CraftingStation = resourceDefinition.CraftedAtCfg.Value ?? ""; val3.MinStationLevel = resourceDefinition.StationLVLCfg.Value; val3.Enabled = true; val3.Icons = (Sprite[])(object)((!((Object)(object)val2 != (Object)null)) ? null : new Sprite[1] { val2 }); val3.Requirements = resourceDefinition.Recipe.RecipeReqs.ToArray(); ItemConfig val4 = val3; ItemManager.Instance.AddItem(new CustomItem(val, FixReferences, val4)); } if (resourceDefinition.Category == ItemCategory.Arrows) { ArcheryAmmoToAdd.Add(resourceDefinition.Prefab); } } return true; } private static void ItemDataConfigModifier(ItemStat target_attribute, float updatedValue, ItemData itemData) { if (itemData != null) { switch (target_attribute) { case ItemStat.slash: itemData.m_shared.m_damages.m_slash = updatedValue; break; case ItemStat.slash_per_level: itemData.m_shared.m_damagesPerLevel.m_slash = updatedValue; break; case ItemStat.blunt: itemData.m_shared.m_damages.m_blunt = updatedValue; break; case ItemStat.blunt_per_level: itemData.m_shared.m_damagesPerLevel.m_blunt = updatedValue; break; case ItemStat.pierce: itemData.m_shared.m_damages.m_pierce = updatedValue; break; case ItemStat.pierce_per_level: itemData.m_shared.m_damagesPerLevel.m_pierce = updatedValue; break; case ItemStat.pickaxe: itemData.m_shared.m_damages.m_pickaxe = updatedValue; break; case ItemStat.pickaxe_per_level: itemData.m_shared.m_damagesPerLevel.m_pickaxe = updatedValue; break; case ItemStat.chop: itemData.m_shared.m_damages.m_chop = updatedValue; break; case ItemStat.chop_per_level: itemData.m_shared.m_damagesPerLevel.m_chop = updatedValue; break; case ItemStat.attack_force: itemData.m_shared.m_attackForce = updatedValue; break; case ItemStat.secondary_attack_force_multiply: itemData.m_shared.m_secondaryAttack.m_forceMultiplier = updatedValue; break; case ItemStat.primary_attack_force_multiply: itemData.m_shared.m_attack.m_forceMultiplier = updatedValue; break; case ItemStat.fire: itemData.m_shared.m_damages.m_fire = updatedValue; break; case ItemStat.fire_per_level: itemData.m_shared.m_damagesPerLevel.m_fire = updatedValue; break; case ItemStat.lightning: itemData.m_shared.m_damages.m_lightning = updatedValue; break; case ItemStat.lightning_per_level: itemData.m_shared.m_damagesPerLevel.m_lightning = updatedValue; break; case ItemStat.frost: itemData.m_shared.m_damages.m_frost = updatedValue; break; case ItemStat.frost_per_level: itemData.m_shared.m_damagesPerLevel.m_frost = updatedValue; break; case ItemStat.poison: itemData.m_shared.m_damages.m_poison = updatedValue; break; case ItemStat.poison_per_level: itemData.m_shared.m_damagesPerLevel.m_poison = updatedValue; break; case ItemStat.spirit: itemData.m_shared.m_damages.m_spirit = updatedValue; break; case ItemStat.spirit_per_level: itemData.m_shared.m_damagesPerLevel.m_spirit = updatedValue; break; case ItemStat.block_armor: itemData.m_shared.m_blockPower = updatedValue; break; case ItemStat.block_armor_per_level: itemData.m_shared.m_blockPowerPerLevel = updatedValue; break; case ItemStat.parry: itemData.m_shared.m_timedBlockBonus = updatedValue; break; case ItemStat.block_force: itemData.m_shared.m_deflectionForce = updatedValue; break; case ItemStat.block_force_per_level: itemData.m_shared.m_deflectionForcePerLevel = updatedValue; break; case ItemStat.primary_attack_stamina: itemData.m_shared.m_attack.m_attackStamina = updatedValue; break; case ItemStat.primary_attack_eitr: itemData.m_shared.m_attack.m_attackEitr = updatedValue; break; case ItemStat.primary_attack_flat_health_cost: itemData.m_shared.m_attack.m_attackHealth = updatedValue; break; case ItemStat.primary_attack_percent_health_cost: itemData.m_shared.m_attack.m_attackHealthPercentage = updatedValue; break; case ItemStat.primary_attack_health_returned: itemData.m_shared.m_attack.m_attackHealthReturnHit = updatedValue; break; case ItemStat.primary_attack_damage_bonus_per_missing_hp: itemData.m_shared.m_attack.m_damageMultiplierPerMissingHP = updatedValue; break; case ItemStat.primary_attack_projectile_count: itemData.m_shared.m_attack.m_projectiles = (int)updatedValue; break; case ItemStat.secondary_attack_stamina: itemData.m_shared.m_secondaryAttack.m_attackStamina = updatedValue; break; case ItemStat.secondary_attack_eitr: itemData.m_shared.m_secondaryAttack.m_attackEitr = updatedValue; break; case ItemStat.secondary_attack_flat_health_cost: itemData.m_shared.m_secondaryAttack.m_attackHealth = updatedValue; break; case ItemStat.secondary_attack_percent_health_cost: itemData.m_shared.m_secondaryAttack.m_attackHealthPercentage = updatedValue; break; case ItemStat.movement_speed: itemData.m_shared.m_movementModifier = updatedValue; break; case ItemStat.bow_draw_speed: itemData.m_shared.m_attack.m_drawDurationMin = updatedValue; break; case ItemStat.crossbow_reload_speed: itemData.m_shared.m_attack.m_reloadTime = updatedValue; break; case ItemStat.crossbow_reload_stamina_drain: itemData.m_shared.m_attack.m_reloadStaminaDrain = updatedValue; break; case ItemStat.draw_stamina_drain: itemData.m_shared.m_attack.m_drawStaminaDrain = updatedValue; break; case ItemStat.projectile_velocity: itemData.m_shared.m_attack.m_projectileVel = updatedValue; break; case ItemStat.projectile_accuracy_max: itemData.m_shared.m_attack.m_projectileAccuracy = 100f - updatedValue; break; case ItemStat.durability: itemData.m_shared.m_maxDurability = updatedValue; break; case ItemStat.durability_per_level: itemData.m_shared.m_durabilityPerLevel = updatedValue; break; case ItemStat.max_item_level: itemData.m_shared.m_maxQuality = (int)updatedValue; break; case ItemStat.amount: itemData.m_shared.m_maxStackSize = (int)updatedValue; break; case ItemStat.tool_level: itemData.m_shared.m_toolTier = (int)updatedValue; break; case ItemStat.food_health: itemData.m_shared.m_food = updatedValue; break; case ItemStat.food_stamina: itemData.m_shared.m_foodStamina = updatedValue; break; case ItemStat.food_eitr: itemData.m_shared.m_foodEitr = updatedValue; break; case ItemStat.food_regen: itemData.m_shared.m_foodRegen = updatedValue; break; case ItemStat.food_duration: itemData.m_shared.m_foodBurnTime = updatedValue; break; default: ModLogger.LogWarning($"Unknown item stat {target_attribute} for {itemData.m_shared.m_name}"); break; } } } private static bool ValidateRecipeConfig(ItemDefinition itemdef) { //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: 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_00c8: Expected O, but got Unknown List<RequirementConfig> list = new List<RequirementConfig>(); try { string[] array = itemdef.Recipe.RecipeConfig.Value.Split(new char[1] { '|' }); foreach (string text in array) { string[] array2 = text.Split(new char[1] { ',' }); if (array2.Length == 1) { return false; } if (array2.Length != 3) { ModLogger.LogWarning("Invalid (" + itemdef.Name + ") recipe config detected: " + text + ". Needs three entries eg: Wood,1,1"); return false; } list.Add(new RequirementConfig { Item = array2[0], Amount = int.Parse(array2[1]), AmountPerLevel = int.Parse(array2[2]) }); } itemdef.Recipe.RecipeReqs = list; return true; } catch { ModLogger.LogWarning("Recipe is Invalid. Should have the format of Wood,1,1|Stone,2,0 - Prefab,cost,upgrade."); return false; } } private static void BuildRecipeReqsFromDefault(ItemDefinition itemdef) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: 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_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Expected O, but got Unknown List<RequirementConfig> list = new List<RequirementConfig>(); foreach (RecipeIngredient recipeItem in itemdef.Recipe.RecipeItems) { list.Add(new RequirementConfig { Item = recipeItem.Prefab, Amount = recipeItem.Amount, AmountPerLevel = recipeItem.UpgradeCost }); } itemdef.Recipe.RecipeReqs = list; } private static string BuildStringRecipeFromItemDef(ItemDefinition itemdef) { List<string> list = new List<string>(); foreach (RecipeIngredient recipeItem in itemdef.Recipe.RecipeItems) { list.Add($"{recipeItem.Prefab},{recipeItem.Amount},{recipeItem.UpgradeCost}"); } return string.Join("|", list.ToArray()); } private static bool ModifyItemRecipeCraftedAt(ItemDefinition itemdef) { if ((Object)(object)ObjectDB.instance == (Object)null || ObjectDB.instance.m_recipes == null) { return false; } int recipeIndexByPrefab = GetRecipeIndexByPrefab(itemdef.Prefab); if (recipeIndexByPrefab == -1) { ModLogger.LogWarning("Recipe of " + itemdef.Prefab + " not found in ObjectDB, recipe will not be modified."); return false; } GameObject prefab = PrefabManager.Instance.GetPrefab(itemdef.CraftedAtCfg.Value); CraftingStation val = ((prefab != null) ? prefab.GetComponent<CraftingStation>() : null); if ((Object)(object)val == (Object)null) { ModLogger.LogWarning("Crafting Station " + itemdef.CraftedAtCfg.Value + " prefab not found, or does not have a crafting station componet."); return false; } ObjectDB.instance.m_recipes[recipeIndexByPrefab].m_craftingStation = val; ObjectDB.instance.m_recipes[recipeIndexByPrefab].m_repairStation = val; return true; } private static void ModifyItemRecipeInODB(ItemDefinition itemdef) { //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Expected O, but got Unknown if ((Object)(object)ObjectDB.instance == (Object)null || ObjectDB.instance.m_recipes == null) { return; } int recipeIndexByPrefab = GetRecipeIndexByPrefab(itemdef.Prefab); if (recipeIndexByPrefab == -1) { ModLogger.LogWarning("Recipe of " + itemdef.Prefab + " not found in ObjectDB, Recipe will not be modified."); return; } Recipe val = ObjectDB.instance.m_recipes[recipeIndexByPrefab]; Recipe val2 = val; List<Requirement> list = new List<Requirement>(); foreach (RequirementConfig recipeReq in itemdef.Recipe.RecipeReqs) { GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(recipeReq.Item); if ((Object)(object)itemPrefab == (Object)null) { ModLogger.LogWarning("Recipe for " + itemdef.Prefab + " has an invalid requirement " + recipeReq.Item + "."); return; } list.Add(new Requirement { m_resItem = itemPrefab.GetComponent<ItemDrop>(), m_amount = recipeReq.Amount, m_amountPerLevel = recipeReq.AmountPerLevel }); } val2.m_resources = list.ToArray(); int num = ObjectDB.instance.m_recipes.IndexOf(val); if (num > -1) { ObjectDB.instance.m_recipes[num] = val2; itemdef.Recipe.ResolvedRecipe = val2; } else { ModLogger.LogWarning("Recipe " + ((Object)val).name + " not found in ObjectDB."); } } private static void EnsureRecipeInDB(ItemDefinition itemdef) { if (!((Object)(object)ObjectDB.instance == (Object)null) && ObjectDB.instance.m_recipes != null && GetRecipeIndexByPrefab(itemdef.Prefab) == -1 && (Object)(object)itemdef.Recipe.ResolvedRecipe != (Object)null) { ObjectDB.instance.m_recipes.Add(itemdef.Recipe.ResolvedRecipe); } } private static void EnableDisableItemInDB(ItemDefinition itemdef, bool enable) { if ((Object)(object)ObjectDB.instance == (Object)null || ObjectDB.instance.m_recipes == null) { return; } int recipeIndexByPrefab = GetRecipeIndexByPrefab(itemdef.Prefab); if (recipeIndexByPrefab == -1) { if ((Object)(object)itemdef.Recipe.ResolvedRecipe != (Object)null) { itemdef.Recipe.ResolvedRecipe.m_enabled = enable; ObjectDB.instance.m_recipes.Add(itemdef.Recipe.ResolvedRecipe); } else { ModLogger.LogWarning("Recipe of " + itemdef.Prefab + " not found in ObjectDB and no cached recipe to re-add."); } } else { ObjectDB.instance.m_recipes[recipeIndexByPrefab].m_enabled = enable; itemdef.Recipe.ResolvedRecipe = ObjectDB.instance.m_recipes[recipeIndexByPrefab]; } } private static void ModifyItemRecipeLevel(ItemDefinition itemdef, int level) { if (!((Object)(object)ObjectDB.instance == (Object)null) && ObjectDB.instance.m_recipes != null) { int recipeIndexByPrefab = GetRecipeIndexByPrefab(itemdef.Prefab); if (recipeIndexByPrefab == -1) { ModLogger.LogWarning("Recipe of " + itemdef.Prefab + " not found in ObjectDB, required level will not be modified."); return; } ObjectDB.instance.m_recipes[recipeIndexByPrefab].m_minStationLevel = level; itemdef.Recipe.ResolvedRecipe = ObjectDB.instance.m_recipes[recipeIndexByPrefab]; } } private static void ModifyItemRecipeCraftAmount(ItemDefinition itemdef, int amount) { if (!((Object)(object)ObjectDB.instance == (Object)null) && ObjectDB.instance.m_recipes != null) { int recipeIndexByPrefab = GetRecipeIndexByPrefab(itemdef.Prefab); if (recipeIndexByPrefab == -1) { ModLogger.LogWarning("Recipe of " + itemdef.Prefab + " not found in ObjectDB, craft amount will not be modified."); return; } ObjectDB.instance.m_recipes[recipeIndexByPrefab].m_amount = amount; itemdef.Recipe.ResolvedRecipe = ObjectDB.instance.m_recipes[recipeIndexByPrefab]; } } private static int GetRecipeIndexByPrefab(string prefab) { return ObjectDB.instance.m_recipes.FindIndex((Recipe m) => (Object)(object)m.m_item != (Object)null && ((Object)m.m_item).name == prefab); } private static void SetItemDamageModifier(DamageModifier modifier, DamageType type, ItemData itemData) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0082: 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_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0094: 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_005c: Unknown result type (might be due to invalid IL or missing references) //IL_005d: 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_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) List<DamageModPair> list = itemData.m_shared.m_damageModifiers.Where((DamageModPair entry) => entry.m_type != type).ToList(); if (list.Count == 0) { itemData.m_shared.m_damageModifiers.Clear(); itemData.m_shared.m_damageModifiers.Add(new DamageModPair { m_modifier = modifier, m_type = type }); } else { list.Add(new DamageModPair { m_modifier = modifier, m_type = type }); itemData.m_shared.m_damageModifiers = list; } } private static void UpdateItemInPlayerInventory(string prefab, Action<ItemData> callback) { if ((Object)(object)Player.m_localPlayer == (Object)null) { return; } foreach (ItemData allItem in ((Humanoid)Player.m_localPlayer).m_inventory.GetAllItems()) { if (allItem != null && !((Object)(object)allItem.m_dropPrefab == (Object)null) && !(((Object)allItem.m_dropPrefab).name != prefab)) { callback(allItem); } } } private static void EnqueueWorldUpdate(string prefab, Action<ItemData> callback) { ThreadingHelper instance = ThreadingHelper.Instance; if (!((Object)(object)instance == (Object)null)) { pendingWorldUpdates.Add(new KeyValuePair<string, Action<ItemData>>(prefab, callback)); if (!worldUpdateScheduled) { worldUpdateScheduled = true; ((MonoBehaviour)instance).StartCoroutine(DrainWorldUpdates()); } } } private static IEnumerator DrainWorldUpdates() { yield return null; try { if (pendingWorldUpdates.Count <= 0) { yield break; } GameObject[] array = Resources.FindObjectsOfTypeAll<GameObject>(); ItemDrop val2 = default(ItemDrop); foreach (GameObject val in array) { if ((Object)(object)val == (Object)null || !val.TryGetComponent<ItemDrop>(ref val2)) { continue; } foreach (KeyValuePair<string, Action<ItemData>> pendingWorldUpdate in pendingWorldUpdates) { if (((Object)val).name == pendingWorldUpdate.Key || ((Object)val).name == pendingWorldUpdate.Key + "(Clone)") { pendingWorldUpdate.Value(val2.m_itemData); } } } } finally { pendingWorldUpdates.Clear(); worldUpdateScheduled = false; } } private static void AddAmmoItemsToArcheryTarget() { if (ArcheryAmmoToAdd.Count == 0) { return; } GameObject prefab = PrefabManager.Instance.GetPrefab("piece_ArcheryTarget"); if ((Object)(object)prefab == (Object)null) { return; } ArcheryTarget componentInChildren = prefab.GetComponentInChildren<ArcheryTarget>(true); if ((Object)(object)componentInChildren == (Object)null) { return; } foreach (string item in ArcheryAmmoToAdd) { ModLogger.LogDebug("Adding " + item + " to Archery Target Ammo Return."); GameObject prefab2 = PrefabManager.Instance.GetPrefab(item); ItemDrop val = ((prefab2 != null) ? prefab2.GetComponent<ItemDrop>() : null); if ((Object)(object)val != (Object)null && !componentInChildren.m_returnAmmo.Contains(val)) { componentInChildren.m_returnAmmo.Add(val); } } } } public enum ItemStat { slash, slash_per_level, blunt, blunt_per_level, pierce, pierce_per_level, pickaxe, pickaxe_per_level, chop, chop_per_level, attack_force, fire, fire_per_level, lightning, lightning_per_level, frost, frost_per_level, poison, poison_per_level, spirit, spirit_per_level, block_armor, block_armor_per_level, parry, block_force, block_force_per_level, primary_attack_stamina, primary_attack_eitr, primary_attack_flat_health_cost, primary_attack_percent_health_cost, primary_attack_health_returned, primary_attack_damage_bonus_per_missing_hp, primary_attack_projectile_count, primary_attack_force_multiply, secondary_attack_stamina, secondary_attack_eitr, secondary_attack_force_multiply, secondary_attack_flat_health_cost, secondary_attack_percent_health_cost, movement_speed, bow_draw_speed, crossbow_reload_speed, crossbow_reload_stamina_drain, draw_stamina_drain, projectile_velocity, projectile_accuracy_max, durability, durability_per_level, max_item_level, amount, tool_level, food_health, food_stamina, food_eitr, food_regen, food_duration } public enum ItemCategory { Arrows, Atgeirs, Axes, Hammers, Shields, Swords, Bows, Spears, Knives, Maces, Fists, Pickaxes, Magics, Misc, Food } public class ItemDefinition { public string Name { get; set; } public string DisplayName { get; set; } public ItemCategory Category { get; set; } public string Prefab { get; set; } public string Icon { get; set; } public string CraftedAt { get; set; } public bool Craftable { get; set; } = true; public int ReqStationlevel { get; set; } public int CraftAmount { get; set; } public Dictionary<ItemStat, ItemStatConfig> ModifableStats { get; set; } = new Dictionary<ItemStat, ItemStatConfig>(); public Dictionary<DamageType, HitCustomDamageMod> DamageMods { get; set; } public RecipeDefinition Recipe { get; set; } public ConfigEntry<string> CraftedAtCfg { get; set; } public ConfigEntry<bool> CraftableCfg { get; set; } public ConfigEntry<int> StationLVLCfg { get; set; } public ConfigEntry<int> CraftAmountCfg { get; set; } } public class HitCustomDamageMod { public bool Configurable { get; set; } = true; public DamageModifier DamageModifier { get; set; } public ConfigEntry<string> DmgModCfg { get; set; } } public class ItemStatConfig { public bool Configurable { get; set; } = true; public bool IsInt { get; set; } public float Default_value { get; set; } public float Min { get; set; } public float Max { get; set; } = 400f; public ConfigEntry<float> Cfg { get; set; } public ConfigEntry<int> CfgInt { get; set; } } public class RecipeDefinition { public ConfigEntry<string> RecipeConfig { get; set; } public List<RecipeIngredient> RecipeItems { get; set; } public List<RequirementConfig> RecipeReqs { get; set; } public Recipe ResolvedRecipe { get; set; } } public class RecipeIngredient { public string Prefab { get; set; } public int Amount { get; set; } public int UpgradeCost { get; set; } } public static class ModContext { public static ManualLogSource Log { get; private set; } public static ConfigFile Cfg { get; private set; } public static string PluginGuid { get; private set; } public static string ConfigFolder { get; private set; } public static AssetBundle AssetBundle { get; set; } public static CustomLocalization Localization { get; set; } public static ConfigEntry<bool> EnableDebugMode { get; private set; } public static ConfigEntry<float> ConfigApplyDelay { get; private set; } public static bool Initialized { get; private set; } public static bool DebugEnabled { get { if (EnableDebugMode != null) { return EnableDebugMode.Value; } return false; } } public static void Initialize(BaseUnityPlugin plugin, ManualLogSource log, string configFolder, AssetBundle assetBundle = null, CustomLocalization localization = null, string configSection = "Common") { //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_00a5: Expected O, but got Unknown //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Expected O, but got Unknown if ((Object)(object)plugin == (Object)null) { throw new ArgumentNullException("plugin"); } Log = log; Cfg = plugin.Config; PluginInfo info = plugin.Info; object obj; if (info == null) { obj = null; } else { BepInPlugin metadata = info.Metadata; obj = ((metadata != null) ? metadata.GUID : null); } if (obj == null) { obj = configFolder; } PluginGuid = (string)obj; ConfigFolder = configFolder; if ((Object)(object)assetBundle != (Object)null) { AssetBundle = assetBundle; } if (localization != null) { Localization = localization; } Cfg.SaveOnConfigSet = true; EnableDebugMode = Cfg.Bind<bool>(configSection, "EnableDebugMode", false, new ConfigDescription("Enables verbose debug logging for the shared item/piece loaders.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { IsAdvanced = true } })); EnableDebugMode.SettingChanged += ModLogger.OnDebugModeChanged; ConfigApplyDelay = ConfigBinder.BindServerConfig(configSection, "Config Apply Delay", 1f, "Delay in seconds before a changed config entry is applied in-game. Coalesces a burst of rapid edits (typing, file reloads, server sync) into a single apply. Set to 0 to apply instantly.", advanced: true, 0f, 10f); Initialized = true; ModLogger.RefreshLevel(); } public static void UseDebugEntry(ConfigEntry<bool> entry) { if (entry != null) { if (EnableDebugMode != null) { EnableDebugMode.SettingChanged -= ModLogger.OnDebugModeChanged; } EnableDebugMode = entry; EnableDebugMode.SettingChanged += ModLogger.OnDebugModeChanged; ModLogger.RefreshLevel(); } } public static void SaveOnSet(bool enabled) { if (Cfg != null) { Cfg.SaveOnConfigSet = enabled; Cfg.Save(); } } } public static class ModLocalization { public static string LocalizationFolder = "Localizations"; public static void AddLocalizations(Assembly assembly = null) { if (assembly == null) { assembly = Assembly.GetExecutingAssembly(); } CustomLocalization val = (ModContext.Localization = ModContext.Localization ?? LocalizationManager.Instance.GetLocalization()); string text = Path.Combine(Paths.ConfigPath, ModContext.ConfigFolder ?? assembly.GetName().Name, LocalizationFolder); Directory.CreateDirectory(text); string[] manifestResourceNames = assembly.GetManifestResourceNames(); foreach (string text2 in manifestResourceNames) { if (text2.IndexOf(LocalizationFolder, StringComparison.OrdinalIgnoreCase) < 0 || !text2.EndsWith(".json", StringComparison.OrdinalIgnoreCase)) { continue; } string text3 = LanguageFromResourceName(text2); if (string.IsNullOrEmpty(text3)) { ModLogger.LogWarning("Could not derive a language name from '" + text2 + "', skipping."); continue; } string text4 = Regex.Replace(ReadEmbeddedResourceFile(text2, assembly), "\\/\\/.*", ""); string text5 = Path.Combine(text, text3 + ".json"); string text6 = text4; if (File.Exists(text5)) { try { Dictionary<string, string> shipped = SimpleJson.DeserializeObject<Dictionary<string, string>>(text4); Dictionary<string, string> dictionary = SimpleJson.DeserializeObject<Dictionary<string, string>>(File.ReadAllText(text5)); ReconcileKeys(shipped, dictionary); text6 = SimpleJson.SerializeObject((object)dictionary); } catch (Exception ex) { ModLogger.LogWarning("Could not merge '" + text5 + "' (" + ex.Message + "); replacing it with the shipped localization."); text6 = text4; } } File.WriteAllText(text5, text6); val.AddJsonFile(text3, text6); ModLogger.LogDebug("Added localization '" + text3 + "' from " + text2); } } private static string LanguageFromResourceName(string embeddedResource) { return embeddedResource.Substring(0, embeddedResource.Length - ".json".Length).Split(new char[1] { '.' }).LastOrDefault(); } private static void ReconcileKeys(Dictionary<string, string> shipped, Dictionary<string, string> onDisk) { List<string> list = onDisk.Keys.Where((string key) => !shipped.ContainsKey(key)).ToList(); foreach (KeyValuePair<string, string> item in shipped) { if (!onDisk.ContainsKey(item.Key)) { ModLogger.LogDebug("Adding missing localization key " + item.Key); onDisk.Add(item.Key, item.Value); } } if (list.Count <= 0) { return; } ModLogger.LogDebug("Removing extra keys " + string.Join(",", list.ToArray()) + "."); foreach (string item2 in list) { onDisk.Remove(item2); } } private static string ReadEmbeddedResourceFile(string filename, Assembly assembly) { using Stream stream = assembly.GetManifestResourceStream(filename); using StreamReader streamReader = new StreamReader(stream); return streamReader.ReadToEnd(); } } public static class ModLogger { public static LogLevel Level = (LogLevel)16; internal static void OnDebugModeChanged(object sender, EventArgs e) { RefreshLevel(); } public static void RefreshLevel() { //IL_000d: Unknown result type (might be due to invalid IL or missing references) Level = (LogLevel)(ModContext.DebugEnabled ? 32 : 16); } public static void SetDebugLogging(bool state) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) Level = (LogLevel)(state ? 32 : 16); } public static void LogDebug(string message) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 if ((int)Level >= 32) { Write((LogLevel)16, "[DEBUG]" + message); } } public static void LogInfo(string message) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 if ((int)Level >= 16) { Write((LogLevel)16, message); } } public static void LogWarning(string message) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Invalid comparison between Unknown and I4 if ((int)Level >= 4) { Write((LogLevel)4, message); } } public static void LogError(string message) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Invalid comparison between Unknown and I4 if ((int)Level >= 2) { Write((LogLevel)2, message); } } private static void Write(LogLevel level, string message) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) ManualLogSource log = ModContext.Log; if (log == null) { Debug.Log((object)$"[Common][{level}] {message}"); } else { log.Log(level, (object)message); } } } public static class PieceLoader { public class LoadedGameObjects { public GameObject Prefab { get; set; } public Sprite Sprite { get; set; } public GameObject ScenePrefab { get; set; } public Piece ScenePiece { get; set; } } public class PieceCost { public string Prefab { get; set; } public int Amount { get; set; } public bool Refundable { get; set; } = true; } public class PieceConfigs { public ConfigEntry<bool> Enabled { get; set; } public ConfigEntry<bool> RequiresWorkbench { get; set; } public ConfigEntry<string> Workbench { get; set; } public ConfigEntry<string> PieceCategory { get; set; } public ConfigEntry<string> PieceCost { get; set; } public List<PieceCost> UpdatedCost { get; set; } = new List<PieceCost>(); } public class BuildPiece { public string Name { get; set; } public bool Enabled { get; set; } = true; public string Prefab { get; set; } public string Sprite { get; set; } public string Category { get; set; } = PieceCategories.Misc; public string PieceTable { get; set; } = PieceTables.Hammer; public string Workbench { get; set; } = "piece_workbench"; public bool RequiresWorkbench { get; set; } = true; public bool AllowedInDungeons { get; set; } public List<PieceCost> PieceCost { get; set; } = new List<PieceCost>(); public LoadedGameObjects Objs { get; set; } public PieceConfigs Cfgs { get; set; } } private static readonly List<BuildPiece> BuildPieces = new List<BuildPiece>(); private static bool PiecesReady = false; public static void Register(BuildPiece jbuildpiece, AssetBundle assetBundle = null) { AssetBundle val = assetBundle ?? ModContext.AssetBundle; if ((Object)(object)val == (Object)null) { ModLogger.LogError("No asset bundle available; piece '" + jbuildpiece.Name + "' will not be registered."); return; } LoadedGameObjects loadedGameObjects = new LoadedGameObjects(); loadedGameObjects.Prefab = LoadBundleAsset<GameObject>(val, jbuildpiece.Prefab, ".prefab"); if ((Object)(object)loadedGameObjects.Prefab == (Object)null) { ModLogger.LogError("Could not find prefab '" + jbuildpiece.Prefab + "' in the asset bundle; piece '" + jbuildpiece.Name + "' will not be registered."); return; } if (!string.IsNullOrEmpty(jbuildpiece.Sprite)) { loadedGameObjects.Sprite = LoadBundleAsset<Sprite>(val, jbuildpiece.Sprite, ".png"); } jbuildpiece.Objs = loadedGameObjects; jbuildpiece.Cfgs = new PieceConfigs(); InitialPieceSetup(jbuildpiece); BuildPieces.Add(jbuildpiece); PrefabManager.OnPrefabsRegistered += ResolveAndApplyScenePrefab; void ResolveAndApplyScenePrefab() { GameObject val2 = ResolveScenePrefab(jbuildpiece.Prefab); if ((Object)(object)val2 == (Object)null) { ModLogger.LogWarning("Could not find a scene prefab named '" + jbuildpiece.Prefab + "' with a Piece component after prefab registration; skipping in-place setup for " + jbuildpiece.Name + "."); } else { jbuildpiece.Objs.ScenePrefab = val2; jbuildpiece.Objs.ScenePiece = val2.GetComponent<Piece>(); PiecesReady = true; ApplyWorkbench(jbuildpiece); ApplyCategory(jbuildpiece); ApplyRecipe(jbuildpiece); } } } private static GameObject ResolveScenePrefab(string prefabName) { GameObject prefab = PrefabManager.Instance.GetPrefab(prefabName); if ((Object)(object)prefab != (Object)null && (Object)(object)prefab.GetComponent<Piece>() != (Object)null) { return prefab; } List<GameObject> list = (from obj in Resources.FindObjectsOfTypeAll<GameObject>() where ((Object)obj).name == prefabName && (Object)(object)obj.GetComponent<Piece>() != (Object)null select obj).ToList(); if (ModContext.DebugEnabled) { ModLogger.LogInfo($"Found {list.Count} scene object(s) named '{prefabName}' with a Piece component."); } return list.FirstOrDefault(); } private static T LoadBundleAsset<T>(AssetBundle bundle, string name, string suffix) where T : Object { T val = bundle.LoadAsset<T>(name); if ((Object)(object)val != (Object)null) { return val; } if (!name.EndsWith(suffix, StringComparison.OrdinalIgnoreCase)) { return bundle.LoadAsset<T>(name + suffix); } return default(T); } private static void InitialPieceSetup(BuildPiece jbuildpiece) { //IL_0316: Unknown result type (might be due to invalid IL or missing references) //IL_031b: Unknown result type (might be due to invalid IL or missing references) //IL_0328: Unknown result type (might be due to invalid IL or missing references) //IL_0335: Unknown result type (might be due to invalid IL or missing references) //IL_0347: Expected O, but got Unknown //IL_0360: Unknown result type (might be due to invalid IL or missing references) //IL_0365: Unknown result type (might be due to invalid IL or missing references) //IL_0376: Unknown result type (might be due to invalid IL or missing references) //IL_0387: Unknown result type (might be due to invalid IL or missing references) //IL_03a2: Unknown result type (might be due to invalid IL or missing references) //IL_03b3: Unknown result type (might be due to invalid IL or missing references) //IL_03c9: Unknown result type (might be due to invalid IL or missing references) //IL_03d7: Expected O, but got Unknown //IL_03ef: Unknown result type (might be due to invalid IL or missing references) //IL_03f9: Expected O, but got Unknown jbuildpiece.Cfgs.RequiresWorkbench = ConfigBinder.BindServerConfig(jbuildpiece.Name, "Requires Workbench", jbuildpiece.RequiresWorkbench, "Whether " + jbuildpiece.Name + " requires a crafting station to be built at all."); jbuildpiece.Cfgs.RequiresWorkbench.SettingChanged += RequiredBench_SettingChanged; jbuildpiece.Cfgs.Workbench = ConfigBinder.BindServerConfig(jbuildpiece.Name, "Workbench", jbuildpiece.Workbench, "The table required to allow building this piece, eg: 'forge', 'piece_workbench', 'blackforge', 'piece_artisanstation'."); jbuildpiece.Cfgs.Workbench.SettingChanged += RequiredBench_SettingChanged; jbuildpiece.Cfgs.Enabled = ConfigBinder.BindServerConfig(jbuildpiece.Name, "Enabled", jbuildpiece.Enabled, "Enable/Disable the " + jbuildpiece.Name + "."); jbuildpiece.Cfgs.Enabled.SettingChanged += BuildRecipeChanged_SettingChanged; jbuildpiece.Cfgs.PieceCategory = ConfigBinder.BindServerConfig(jbuildpiece.Name, "Piece Category", jbuildpiece.Category, "Piece category for building.", PieceCategories.GetAcceptableValueList()); jbuildpiece.Cfgs.PieceCategory.SettingChanged += CraftingCategory_SettingChanged; List<string> list = new List<string>(); foreach (PieceCost item in jbuildpiece.PieceCost) { list.Add($"{item.Prefab},{item.Amount},{item.Refundable}"); } string text = string.Join("|", list.ToArray()); jbuildpiece.Cfgs.PieceCost = ConfigBinder.BindServerConfig(jbuildpiece.Name, "Building Cost", text, "Cost to build. Find item ids: https://valheim.fandom.com/wiki/Item_IDs Format: resouce_id,amount,refund eg: Wood,8,true|LeatherScraps,4,false", (AcceptableValueList<string>)null, advanced: true); if (!PieceRecipeConfigUpdater(jbuildpiece, jbuildpiece.Cfgs.PieceCost.Value, during_runtime: false)) { ModLogger.LogWarning(jbuildpiece.Name + " has an invalid piece cost. The default will be used instead."); PieceRecipeConfigUpdater(jbuildpiece, text, during_runtime: false); } jbuildpiece.Cfgs.PieceCost.SettingChanged += BuildRecipeChanged_SettingChanged; PieceConfigDrawer.Attach(jbuildpiece); if (jbuildpiece.Cfgs.UpdatedCost.Count == 0) { ModLogger.LogError(jbuildpiece.Name + " has no valid build cost (empty or unparseable PieceCost); skipping registration so it cannot be built for free."); return; } List<RequirementConfig> list2 = new List<RequirementConfig>(); foreach (PieceCost item2 in jbuildpiece.Cfgs.UpdatedCost) { list2.Add(new RequirementConfig { Item = item2.Prefab, Amount = item2.Amount, Recover = item2.Refundable }); } PieceConfig val = new PieceConfig { CraftingStation = ResolveWorkbenchName(jbuildpiece), PieceTable = jbuildpiece.PieceTable, Category = jbuildpiece.Cfgs.PieceCategory.Value, AllowedInDungeons = jbuildpiece.AllowedInDungeons, Icon = jbuildpiece.Objs.Sprite, Requirements = list2.ToArray() }; PieceManager.Instance.AddPiece(new CustomPiece(jbuildpiece.Objs.Prefab, true, val)); void BuildRecipeChanged_SettingChanged(object sender, EventArgs e) { if (PiecesReady && !((Object)(object)jbuildpiece.Objs.ScenePiece == (Object)null)) { ConfigChangeDebouncer.Schedule(sender, delegate { if (sender is ConfigEntry<string> val2) { if (ModContext.DebugEnabled) { ModLogger.LogInfo("Recieved new piece config " + val2.Value); } if (!PieceRecipeConfigUpdater(jbuildpiece, val2.Value)) { return; } } ApplyRecipe(jbuildpiece); }); } } void CraftingCategory_SettingChanged(object sender, EventArgs e) { if (PiecesReady && !((Object)(object)jbuildpiece.Objs.ScenePiece == (Object)null)) { ConfigChangeDebouncer.Schedule(jbuildpiece.Cfgs.PieceCategory, delegate { ApplyCategory(jbuildpiece); }); } } void RequiredBench_SettingChanged(object sender, EventArgs e) { if (PiecesReady && !((Object)(object)jbuildpiece.Objs.ScenePiece == (Object)null)) { ConfigChangeDebouncer.Schedule(jbuildpiece.Cfgs.Workbench, delegate { ApplyWorkbench(jbuildpiece); }); } } } private static string ResolveWorkbenchName(BuildPiece jbuildpiece) { bool num = jbuildpiece.Cfgs.RequiresWorkbench?.Value ?? true; string value = jbuildpiece.Cfgs.Workbench.Value; if (!num || string.IsNullOrEmpty(value) || value.ToLower() == "none") { return null; } return value; } private static void ApplyWorkbench(BuildPiece jbuildpiece) { Piece scenePiece = jbuildpiece.Objs.ScenePiece; if ((Object)(object)scenePiece == (Object)null) { return; } string text = ResolveWorkbenchName(jbuildpiece); if (text == null) { if (ModContext.DebugEnabled) { ModLogger.LogInfo("Setting required crafting station for " + jbuildpiece.Name + " to none."); } scenePiece.m_craftingStation = null; return; } GameObject prefab = PrefabManager.Instance.GetPrefab(text); CraftingStation val = ((prefab != null) ? prefab.GetComponent<CraftingStation>() : null); if ((Object)(object)val == (Object)null) { ModLogger.LogWarning("Required crafting station does not exist or does not have a crafting station component, check your prefab name (" + text + ")."); return; } if (ModContext.DebugEnabled) { ModLogger.LogInfo("Setting crafting station to " + text + "."); } scenePiece.m_craftingStation = val; } private static void ApplyCategory(BuildPiece jbuildpiece) { //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) Piece scenePiece = jbuildpiece.Objs.ScenePiece; if (!((Object)(object)scenePiece == (Object)null)) { PieceCategory? val = PieceManager.Instance.GetPieceCategory(jbuildpiece.Cfgs.PieceCategory.Value); if (!val.HasValue) { val = PieceManager.Instance.AddPieceCategory(jbuildpiece.Cfgs.PieceCategory.Value); } scenePiece.m_category = val.Value; } } private static void ApplyRecipe(BuildPiece jbuildpiece) { //IL_00d7: 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_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Expected O, but got Unknown //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Expected O, but got Unknown Piece scenePiece = jbuildpiece.Objs.ScenePiece; if ((Object)(object)scenePiece == (Object)null) { return; } if (!jbuildpiece.Cfgs.Enabled.Value) { scenePiece.m_enabled = false; return; } List<RequirementConfig> list = new List<RequirementConfig>(); if (ModContext.DebugEnabled) { ModLogger.LogInfo("Validating and building requirementsConfig"); } foreach (PieceCost item in jbuildpiece.Cfgs.UpdatedCost) { if ((Object)(object)PrefabManager.Instance.GetPrefab(item.Prefab) == (Object)null) { if (ModContext.DebugEnabled) { ModLogger.LogInfo(item.Prefab + " is not a valid prefab, skipping recipe update."); } return; } if (ModContext.DebugEnabled) { ModLogger.LogInfo($"Checking entry {item.