using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Collections.Specialized; using System.ComponentModel; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Versioning; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using System.Threading; using Automatics.AutomaticDoor; using Automatics.AutomaticMapping; using Automatics.AutomaticProcessing; using Automatics.ConsoleCommands; using Automatics.Valheim; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using JetBrains.Annotations; using LitJson; using ModUtils; using NDesk.Options; using Splatform; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("Automatics")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("Automatics")] [assembly: AssemblyCopyright("Copyright (c) 2022-2026 EideeHi")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("1821CB9A-56A9-4013-B268-86F0704773CF")] [assembly: AssemblyFileVersion("1.6.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = "")] [assembly: AssemblyVersion("1.6.0.0")] namespace ModUtils { public class Configuration { private sealed class LocalizedConfigEntry { public ConfigEntryBase Entry { get; set; } public L10N Localization { get; set; } public string Section { get; set; } public string Key { get; set; } public ConfigurationManagerAttributes Attributes { get; set; } public bool CategoryManaged { get; set; } public bool DispNameManaged { get; set; } public bool DescriptionManaged { get; set; } } private const int DefaultOrder = 4096; private static readonly object LocalizedEntriesLock; private static readonly Dictionary LocalizedEntries; private static readonly string[] DescriptionFieldNames; private readonly ConfigFile _config; private readonly L10N _localization; private Logger _logger; private string Section { get; set; } = "general"; private int Order { get; set; } = 4096; static Configuration() { //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Expected O, but got Unknown //IL_00ac: 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_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Expected O, but got Unknown LocalizedEntriesLock = new object(); DescriptionFieldNames = new string[4] { "k__BackingField", "Description", "description", "_description" }; LocalizedEntries = new Dictionary(); if (!TomlTypeConverter.CanConvert(typeof(StringList))) { TomlTypeConverter.AddConverter(typeof(StringList), new TypeConverter { ConvertToObject = (string str, Type type) => (!string.IsNullOrEmpty(str)) ? new StringList(Csv.ParseLine(str, trimUnquotedFields: true)) : new StringList(), ConvertToString = delegate(object obj, Type type) { StringList source = (StringList)obj; return string.Join(", ", source.Select(Csv.Escape)); } }); } if (!TomlTypeConverter.CanConvert(typeof(KeyboardShortcut))) { TomlTypeConverter.AddConverter(typeof(KeyboardShortcut), new TypeConverter { ConvertToObject = (string str, Type type) => KeyboardShortcut.Deserialize(str), ConvertToString = delegate(object obj, Type type) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) KeyboardShortcut val = (KeyboardShortcut)obj; return ((KeyboardShortcut)(ref val)).Serialize(); } }); } } public Configuration(ConfigFile config, L10N localization) { _config = config; _localization = localization; } internal static void RefreshAllLocalizedMetadata() { LocalizedConfigEntry[] array; lock (LocalizedEntriesLock) { array = LocalizedEntries.Values.ToArray(); } LocalizedConfigEntry[] array2 = array; for (int i = 0; i < array2.Length; i++) { RefreshLocalizedMetadata(array2[i]); } } private static void RegisterLocalizedEntry(ConfigEntryBase entry, L10N localization, string section, string key, ConfigurationManagerAttributes attributes, bool categoryManaged, bool dispNameManaged, bool descriptionManaged) { LocalizedConfigEntry localizedConfigEntry = new LocalizedConfigEntry { Entry = entry, Localization = localization, Section = section, Key = key, Attributes = attributes, CategoryManaged = categoryManaged, DispNameManaged = dispNameManaged, DescriptionManaged = descriptionManaged }; lock (LocalizedEntriesLock) { LocalizedEntries[entry] = localizedConfigEntry; } RefreshLocalizedMetadata(localizedConfigEntry); } private static void RefreshLocalizedMetadata(LocalizedConfigEntry entry) { //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Expected O, but got Unknown if (entry?.Entry == null || entry.Localization == null) { return; } try { ConfigurationManagerAttributes attributes = entry.Attributes; if (attributes != null) { if (entry.CategoryManaged) { attributes.Category = entry.Localization.Translate("@config_" + entry.Section + "_section"); } if (entry.DispNameManaged) { attributes.DispName = entry.Localization.Translate("@config_" + entry.Section + "_" + entry.Key + "_name"); } string text = (attributes.Description = (entry.DescriptionManaged ? entry.Localization.Translate("@config_" + entry.Section + "_" + entry.Key + "_description") : attributes.Description)); ConfigDescription description = entry.Entry.Description; AcceptableValueBase val = ((description != null) ? description.AcceptableValues : null); object[] array = ReplaceConfigurationManagerAttributes((description != null) ? description.Tags : null, attributes); ConfigDescription description2 = new ConfigDescription(text, val, array); if (!TrySetEntryDescription(entry.Entry, description2)) { Debug.LogError((object)("[ModUtils] Failed to replace ConfigDescription for [" + entry.Section + ":" + entry.Key + "].")); } } } catch (Exception arg) { Debug.LogError((object)$"[ModUtils] Failed to refresh localized config metadata for [{entry.Section}:{entry.Key}]: {arg}"); } } private static object[] ReplaceConfigurationManagerAttributes(object[] tags, ConfigurationManagerAttributes attributes) { if (tags == null || tags.Length == 0) { return new object[1] { attributes }; } bool flag = false; List list = new List(tags.Length); foreach (object obj in tags) { if (obj is ConfigurationManagerAttributes) { if (!flag) { list.Add(attributes); flag = true; } } else { list.Add(obj); } } if (!flag) { list.Add(attributes); } return list.ToArray(); } private static bool TrySetEntryDescription(ConfigEntryBase entry, ConfigDescription description) { MethodInfo methodInfo = AccessTools.PropertySetter(((object)entry).GetType(), "Description") ?? AccessTools.PropertySetter(typeof(ConfigEntryBase), "Description"); if (methodInfo != null) { methodInfo.Invoke(entry, new object[1] { description }); return true; } string[] descriptionFieldNames = DescriptionFieldNames; foreach (string text in descriptionFieldNames) { FieldInfo fieldInfo = AccessTools.Field(((object)entry).GetType(), text) ?? AccessTools.Field(typeof(ConfigEntryBase), text); if (!(fieldInfo == null) && typeof(ConfigDescription).IsAssignableFrom(fieldInfo.FieldType)) { fieldInfo.SetValue(entry, description); return true; } } return false; } private void LogSection(string section) { _logger?.Debug("[CONFIG] === " + GetSection(section) + " / [" + section + "]"); } private void LogConfigEntry(ConfigEntry entry, ConfigurationManagerAttributes attributes) { _logger?.Debug("[CONFIG] ==== " + attributes.DispName + " / [" + ((ConfigEntryBase)entry).Definition.Key + "]"); _logger?.Debug("[CONFIG] " + ((ConfigEntryBase)entry).Description.Description); _logger?.Debug("[CONFIG] "); Type type = typeof(T); object defaultValue = ((ConfigEntryBase)entry).DefaultValue; if (attributes.ObjToStr != null) { _logger?.Debug("[CONFIG] - Default value: " + attributes.ObjToStr(defaultValue)); } else if (TomlTypeConverter.CanConvert(type)) { _logger?.Debug("[CONFIG] - Default value: " + TomlTypeConverter.ConvertToString(defaultValue, type)); } else { _logger?.Debug($"[CONFIG] - Default value: {defaultValue}"); } AcceptableValueBase acceptableValues = ((ConfigEntryBase)entry).Description.AcceptableValues; if (acceptableValues != null) { string[] array = acceptableValues.ToDescriptionString().Split('\n'); foreach (string text in array) { _logger?.Debug("[CONFIG] - " + text); } } else if (type.IsEnum) { List list = (from x in Enum.GetValues(type).OfType() select Enum.GetName(type, x)).ToList(); _logger?.Debug("[CONFIG] - Acceptable values: " + string.Join(", ", list)); if (type.GetCustomAttributes(typeof(FlagsAttribute), inherit: false).Any()) { IEnumerable values = list.Where((string x) => !string.Equals(x, "none", StringComparison.OrdinalIgnoreCase) && !string.Equals(x, "all", StringComparison.OrdinalIgnoreCase)).Take(2); _logger?.Debug("[CONFIG] - Multiple values can be set at the same time by separating them with , (e.g. " + string.Join(", ", values) + ")"); } } _logger?.Debug("[CONFIG] "); } public void SetDebugLogger(Logger logger) { _logger = logger; } public void ChangeSection(string section, int initialOrder = 4096) { Section = section; Order = initialOrder; if (_logger != null) { LogSection(Section); } } private ConfigEntry Bind(string section, int order, string key, T defaultValue, AcceptableValueBase acceptableValue = null, Action initializer = null) { //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Expected O, but got Unknown L10N.EnsurePatched(); string section2 = GetSection(section); string name = GetName(section, key); ConfigurationManagerAttributes configurationManagerAttributes = new ConfigurationManagerAttributes { Category = section2, Order = order, DispName = name, CustomDrawer = ConfigurationCustomDrawer.Get(typeof(T), acceptableValue) }; initializer?.Invoke(configurationManagerAttributes); bool categoryManaged = string.Equals(configurationManagerAttributes.Category, section2, StringComparison.Ordinal); bool dispNameManaged = string.Equals(configurationManagerAttributes.DispName, name, StringComparison.Ordinal); bool flag = string.IsNullOrEmpty(configurationManagerAttributes.Description); string text = (configurationManagerAttributes.Description = (flag ? GetDescription(section, key) : configurationManagerAttributes.Description)); ConfigEntry val = _config.Bind(section, key, defaultValue, new ConfigDescription(text, acceptableValue, new object[1] { configurationManagerAttributes })); RegisterLocalizedEntry((ConfigEntryBase)(object)val, _localization, section, key, configurationManagerAttributes, categoryManaged, dispNameManaged, flag); if (_logger != null) { LogConfigEntry(val, configurationManagerAttributes); } return val; } public ConfigEntry Bind(string section, string key, T defaultValue, AcceptableValueBase acceptableValue = null, Action initializer = null) { return Bind(section, Order--, key, defaultValue, acceptableValue, initializer); } public ConfigEntry Bind(string section, string key, T defaultValue, (T, T) acceptableValue, Action initializer = null) where T : IComparable { var (val, val2) = acceptableValue; return Bind(section, key, defaultValue, (AcceptableValueBase)(object)new AcceptableValueRange(val, val2), initializer); } public ConfigEntry Bind(string key, T defaultValue, AcceptableValueBase acceptableValue = null, Action initializer = null) { return Bind(Section, key, defaultValue, acceptableValue, initializer); } public ConfigEntry Bind(string key, T defaultValue, (T, T) acceptableValue, Action initializer = null) where T : IComparable { return Bind(Section, key, defaultValue, acceptableValue, initializer); } private string GetSection(string section) { return _localization.Translate("@config_" + section + "_section"); } private string GetName(string section, string key) { return _localization.Translate("@config_" + section + "_" + key + "_name"); } private string GetDescription(string section, string key) { return _localization.Translate("@config_" + section + "_" + key + "_description"); } } public class StringList : ICollection, IEnumerable, IEnumerable { private readonly HashSet _values; public int Count => _values.Count; public bool IsReadOnly => false; public StringList() { _values = new HashSet(); } public StringList(IEnumerable collection) { _values = new HashSet(collection); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } public IEnumerator GetEnumerator() { return _values.GetEnumerator(); } public void Add(string item) { _values.Add(item); } public void Clear() { _values.Clear(); } public bool Contains(string item) { return _values.Contains(item); } public void CopyTo(string[] array, int arrayIndex) { _values.CopyTo(array, arrayIndex); } public bool Remove(string item) { return _values.Remove(item); } public bool TryAdd(string item) { return _values.Add(item); } } public class LocalizedDescriptionAttribute : DescriptionAttribute { private readonly string _prefix; private readonly string _key; public override string Description => L10N.Translate(_prefix, _key); public LocalizedDescriptionAttribute(string prefix, string key) : base(key) { _prefix = prefix; _key = key; } public LocalizedDescriptionAttribute(string key) : this("", key) { } } public class AcceptableValueEnum : AcceptableValueBase where T : Enum { private readonly bool _isFlags; private readonly IList _values; public AcceptableValueEnum(params T[] values) : base(typeof(T)) { _isFlags = ((AcceptableValueBase)this).ValueType.GetCustomAttributes(typeof(FlagsAttribute), inherit: false).Any(); _values = MakeValues(((AcceptableValueBase)this).ValueType, (IReadOnlyCollection)(object)values, _isFlags); } private static IList MakeValues(Type type, IReadOnlyCollection values, bool isFlags) { object collection; if (values.Count != 0) { collection = values; } else { collection = Enum.GetValues(type).OfType(); } List list = new List((IEnumerable)collection); if (!isFlags) { return list; } HashSet hashSet = new HashSet(); foreach (long item in list.Select((T @enum) => Convert.ToInt64(@enum))) { long[] array = hashSet.ToArray(); foreach (long num in array) { hashSet.Add(num | item); } hashSet.Add(item); } return hashSet.Select((long x) => Enum.ToObject(type, x)).Cast().ToList(); } public override object Clamp(object value) { if (!((AcceptableValueBase)this).IsValid(value)) { return _values[0]; } return value; } public override bool IsValid(object value) { if (value is T item) { return _values.Contains(item); } if (!(value is IConvertible)) { return false; } long @long = Convert.ToInt64(value); return _values.Any((T x) => Convert.ToInt64(x) == @long); } public override string ToDescriptionString() { StringBuilder stringBuilder = new StringBuilder(); Type type = typeof(T); List list = (from x in _values where Enum.IsDefined(type, x) select Enum.GetName(type, x)).ToList(); stringBuilder.Append("# Acceptable values: ").Append(string.Join(", ", list)); if (!_isFlags) { return stringBuilder.ToString(); } List list2 = list.Where((string x) => !string.Equals(x, "none", StringComparison.OrdinalIgnoreCase) && !string.Equals(x, "all", StringComparison.OrdinalIgnoreCase)).Take(2).ToList(); if (list2.Count == 2) { stringBuilder.Append('\n').Append("# Multiple values can be set at the same time by separating them with , (e.g. ").Append(string.Join(", ", list2)) .Append(")"); } return stringBuilder.ToString(); } } public static class ConfigurationCustomDrawer { public delegate bool IsMatchConfig(Type type, AcceptableValueBase acceptableValue); public delegate Action CustomDrawerSupplier(); private const string L10NPrefix = "mod_utils"; private const string EnabledKey = "@config_button_enabled"; private const string DisabledKey = "@config_button_disabled"; private const string AddKey = "@config_button_add"; private const string RemoveKey = "@config_button_remove"; private static readonly Dictionary CustomDrawers; private static bool _defaultTranslationsInitialized; private static readonly Dictionary> BuiltinDrawerTranslations; private static readonly Dictionary> CustomDrawerTranslations; private static readonly Dictionary OwnedDefaults; static ConfigurationCustomDrawer() { BuiltinDrawerTranslations = new Dictionary>(StringComparer.OrdinalIgnoreCase) { { "English", new Dictionary { { "@config_button_enabled", "Enabled" }, { "@config_button_disabled", "Disabled" }, { "@config_button_add", "Add" }, { "@config_button_remove", "Remove" } } }, { "Japanese", new Dictionary { { "@config_button_enabled", "有効" }, { "@config_button_disabled", "無効" }, { "@config_button_add", "追加" }, { "@config_button_remove", "削除" } } } }; CustomDrawerTranslations = new Dictionary>(StringComparer.OrdinalIgnoreCase); OwnedDefaults = new Dictionary(); CustomDrawers = new Dictionary { { IsBool, () => Bool }, { IsFloatWithRange, () => FloatSlider }, { IsStringList, StringList }, { IsFlagsEnum, () => Flags } }; } public static void RegisterDefaultDrawerTranslation(string language, string key, string value) { if (!CustomDrawerTranslations.TryGetValue(language, out var value2)) { value2 = new Dictionary(); CustomDrawerTranslations[language] = value2; } value2[key] = value; if (_defaultTranslationsInitialized) { RefreshDefaultTranslations(); } } private static void EnsureDefaultTranslations() { if (!_defaultTranslationsInitialized) { _defaultTranslationsInitialized = TryAddDefaultTranslations(); } } internal static void RefreshDefaultTranslations() { _defaultTranslationsInitialized = false; _defaultTranslationsInitialized = TryAddDefaultTranslations(); if (!_defaultTranslationsInitialized) { Debug.LogWarning((object)"[ModUtils] Failed to refresh custom drawer fallback translations for the current language."); } } private static Dictionary ResolveDrawerTranslations(string language) { Dictionary dictionary = new Dictionary(BuiltinDrawerTranslations["English"]); if (CustomDrawerTranslations.TryGetValue("English", out var value)) { foreach (KeyValuePair item in value) { dictionary[item.Key] = item.Value; } } if (!string.Equals(language, "English", StringComparison.OrdinalIgnoreCase)) { if (BuiltinDrawerTranslations.TryGetValue(language, out var value2)) { foreach (KeyValuePair item2 in value2) { dictionary[item2.Key] = item2.Value; } } if (CustomDrawerTranslations.TryGetValue(language, out var value3)) { foreach (KeyValuePair item3 in value3) { dictionary[item3.Key] = item3.Value; } } } return dictionary; } private static bool TryAddDefaultTranslations() { Localization instance; try { instance = Localization.instance; } catch (Exception) { return false; } if (instance == null) { return false; } Dictionary field = Reflections.GetField>(instance, "m_translations"); if (field == null) { return false; } string text; try { text = instance.GetSelectedLanguage(); } catch (Exception) { return false; } if (string.IsNullOrEmpty(text)) { text = "English"; } foreach (KeyValuePair item in ResolveDrawerTranslations(text)) { string translationKey = L10N.GetTranslationKey("mod_utils", item.Key); if (field.TryGetValue(translationKey, out var value)) { if (OwnedDefaults.TryGetValue(translationKey, out var value2) && value == value2) { field[translationKey] = item.Value; } } else { field[translationKey] = item.Value; } OwnedDefaults[translationKey] = item.Value; } return true; } private static bool IsBool(Type type, AcceptableValueBase acceptableValue) { return type == typeof(bool); } private static bool IsFloatWithRange(Type type, AcceptableValueBase acceptableValue) { if (type == typeof(float)) { return acceptableValue is AcceptableValueRange; } return false; } private static bool IsStringList(Type type, AcceptableValueBase acceptableValue) { return type == typeof(StringList); } private static bool HasFlagsAttribute(Type type) { if (type.IsEnum) { return type.GetCustomAttributes(typeof(FlagsAttribute), inherit: false).Any(); } return false; } private static bool IsFlagsEnum(Type type, AcceptableValueBase acceptableValue) { return HasFlagsAttribute(type); } public static void Bool(ConfigEntryBase entry) { EnsureDefaultTranslations(); bool flag = (bool)entry.BoxedValue; string text = L10N.Translate("mod_utils", flag ? "@config_button_enabled" : "@config_button_disabled"); bool flag2 = GUILayout.Toggle(flag, text, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) }); if (flag2 != flag) { entry.BoxedValue = flag2; } } public static void FloatSlider(ConfigEntryBase entry) { AcceptableValueRange val = (AcceptableValueRange)(object)entry.Description.AcceptableValues; float num = (float)entry.BoxedValue; float minValue = val.MinValue; float maxValue = val.MaxValue; float num2 = GUILayout.HorizontalSlider(num, minValue, maxValue, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) }); num2 = Mathf.Floor(num2 * 100f) / 100f; if (Math.Abs(num2 - num) > Mathf.Abs(maxValue - minValue) / 1000f) { entry.BoxedValue = num2; } string text = num.ToString("0.00", CultureInfo.InvariantCulture); string text2 = GUILayout.TextField(text, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(50f) }); if (text2 == text) { return; } try { num2 = (float)Convert.ToDouble(text2, CultureInfo.InvariantCulture); object boxedValue = Convert.ChangeType(((AcceptableValueBase)val).Clamp((object)num2), entry.SettingType, CultureInfo.InvariantCulture); entry.BoxedValue = boxedValue; } catch (FormatException) { } } private static Action StringList() { string inputText = ""; return delegate(ConfigEntryBase entry) { //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Expected O, but got Unknown //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Expected O, but got Unknown //IL_013f: Unknown result type (might be due to invalid IL or missing references) EnsureDefaultTranslations(); int num = Mathf.Min(Screen.width, 650); int num2 = num - Mathf.RoundToInt((float)num / 2.5f) - 115; string text = L10N.Translate("mod_utils", "@config_button_add"); string text2 = L10N.Translate("mod_utils", "@config_button_remove"); StringList stringList = new StringList((StringList)entry.BoxedValue); GUILayout.BeginVertical((GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.MaxWidth((float)num2) }); GUILayout.BeginHorizontal(Array.Empty()); inputText = GUILayout.TextField(inputText, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) }); if (GUILayout.Button(text, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(false) }) && !string.IsNullOrEmpty(inputText)) { if (stringList.TryAdd(inputText)) { entry.BoxedValue = stringList; } inputText = ""; } GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(Array.Empty()); double num3 = 0.0; foreach (string item in stringList.ToList()) { int num4 = Mathf.FloorToInt(GUI.skin.label.CalcSize(new GUIContent(item)).x) + Mathf.FloorToInt(GUI.skin.button.CalcSize(new GUIContent(text2)).x); num3 += (double)num4; if (num3 > (double)num2) { GUILayout.EndHorizontal(); num3 = num4; GUILayout.BeginHorizontal(Array.Empty()); } GUILayout.Label(item, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(false) }); if (GUILayout.Button(text2, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(false) }) && stringList.Remove(item)) { entry.BoxedValue = stringList; } } GUILayout.EndHorizontal(); GUILayout.EndVertical(); GUILayout.FlexibleSpace(); }; } public static void Flags(ConfigEntryBase entry) { //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Expected O, but got Unknown //IL_00c2: Unknown result type (might be due to invalid IL or missing references) int num = Mathf.Min(Screen.width, 650); int num2 = num - Mathf.RoundToInt((float)num / 2.5f) - 115; Type settingType = entry.SettingType; long num3 = Convert.ToInt64(entry.BoxedValue); AcceptableValueBase acceptableValues = entry.Description.AcceptableValues; GUILayout.BeginVertical((GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.MaxWidth((float)num2) }); int num4 = 0; GUILayout.BeginHorizontal(Array.Empty()); foreach (object value2 in Enum.GetValues(settingType)) { if (acceptableValues != null && !acceptableValues.IsValid(value2)) { continue; } long num5 = Convert.ToInt64(value2); if (num5 != 0L) { string enumLabel = GetEnumLabel(settingType, value2); int num6 = Mathf.FloorToInt(GUI.skin.toggle.CalcSize(new GUIContent(enumLabel + "_")).x); num4 += num6; if (num4 > num2) { GUILayout.EndHorizontal(); num4 = num6; GUILayout.BeginHorizontal(Array.Empty()); } GUI.changed = false; bool flag = GUILayout.Toggle((num3 & num5) == num5, enumLabel, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(false) }); if (GUI.changed) { long value = (flag ? (num3 | num5) : (num3 & ~num5)); entry.BoxedValue = Enum.ToObject(settingType, value); } } } GUILayout.EndHorizontal(); GUI.changed = false; GUILayout.EndVertical(); GUILayout.FlexibleSpace(); } public static Action MultiSelect(Func> allElementSupplier, Func labelGenerator) where T : IComparable { return delegate(ConfigEntryBase entry) { //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Expected O, but got Unknown //IL_0140: Unknown result type (might be due to invalid IL or missing references) int num = Mathf.Min(Screen.width, 650); int num2 = num - Mathf.RoundToInt((float)num / 2.5f) - 115; GUILayout.BeginVertical((GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.MaxWidth((float)num2) }); Type settingType = entry.SettingType; ConstructorInfo constructor = settingType.GetConstructor(new Type[1] { typeof(IEnumerable) }); if ((object)constructor == null) { GUILayout.BeginHorizontal(Array.Empty()); GUILayout.Label($"{settingType} does not define a constructor that takes IEnumerable<{typeof(T)}> as an argument.", Array.Empty()); GUILayout.EndHorizontal(); GUI.changed = false; GUILayout.EndVertical(); GUILayout.FlexibleSpace(); } else { ICollection collection = (ICollection)constructor.Invoke(new object[1] { entry.BoxedValue }); AcceptableValueBase acceptableValues = entry.Description.AcceptableValues; int num3 = 0; GUILayout.BeginHorizontal(Array.Empty()); foreach (T item in allElementSupplier()) { if (acceptableValues == null || acceptableValues.IsValid((object)item)) { string text = labelGenerator(item) ?? item.ToString(); int num4 = Mathf.FloorToInt(GUI.skin.toggle.CalcSize(new GUIContent(text + "_")).x); num3 += num4; if (num3 > num2) { GUILayout.EndHorizontal(); num3 = num4; GUILayout.BeginHorizontal(Array.Empty()); } GUI.changed = false; bool flag = GUILayout.Toggle(collection.Contains(item), text, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(false) }); if (GUI.changed) { if (flag) { collection.Add(item); } else { collection.Remove(item); } entry.BoxedValue = collection; } } } GUILayout.EndHorizontal(); GUI.changed = false; GUILayout.EndVertical(); GUILayout.FlexibleSpace(); } }; } public static void Register(IsMatchConfig matcher, CustomDrawerSupplier supplier) { CustomDrawers[matcher] = supplier; } public static Action Get(Type type, AcceptableValueBase acceptableValue) { return (from x in CustomDrawers where x.Key(type, acceptableValue) select x.Value()).FirstOrDefault(); } private static string GetEnumLabel(Type type, object @object) { return (type.GetMember(Enum.GetName(type, @object) ?? "").FirstOrDefault()?.GetCustomAttributes(typeof(DescriptionAttribute), inherit: false).OfType().FirstOrDefault())?.Description ?? @object.ToString(); } } public sealed class ConfigurationManagerAttributes { public bool? ShowRangeAsPercent; public Action CustomDrawer; public bool? Browsable; public string Category; public object DefaultValue; public bool? HideDefaultButton; public bool? HideSettingName; public string Description; public string DispName; public int? Order; public bool? ReadOnly; public bool? IsAdvanced; public Func ObjToStr; public Func StrToObj; } public static class Csv { public sealed class Parser { private readonly StringBuilder _fieldBuffer; private readonly List _recordBuffer; private readonly string _source; private readonly bool _trimUnquotedFields; private bool _fieldQuoted; private bool _fieldStarted; private bool _inQuotes; private bool _lastTokenWasDelimiter; private bool _quotedFieldClosed; private int _offset; public Parser(string source, int offset = 0, bool trimUnquotedFields = false) { _source = source ?? ""; _offset = offset; _trimUnquotedFields = trimUnquotedFields; _recordBuffer = new List(); _fieldBuffer = new StringBuilder(); } public List> Parse() { List> list = new List>(); int num = -1; while (HasNext()) { List list2 = ParseLine(); int count = list2.Count; if (count != 0) { if (num == -1) { num = count; } else if (num != count) { throw new Exception("Number of fields in a record is not uniform."); } list.Add(list2); } } return list; } public bool HasNext() { return _offset < _source.Length; } public List ParseLine() { _recordBuffer.Clear(); _fieldBuffer.Clear(); _fieldQuoted = false; _fieldStarted = false; _inQuotes = false; _lastTokenWasDelimiter = false; _quotedFieldClosed = false; List list = new List(); bool recordHasContent = false; while (_offset < _source.Length) { char c = _source[_offset++]; if (!ParseChar(c, ref recordHasContent)) { break; } } if (recordHasContent || _fieldStarted || _lastTokenWasDelimiter) { FlushField(); } if (_recordBuffer.Count > 0) { list.AddRange(_recordBuffer); } return list; } private bool ParseChar(char c, ref bool recordHasContent) { switch (c) { case '"': recordHasContent = true; if (_inQuotes) { if (_offset < _source.Length && _source[_offset] == '"') { _fieldBuffer.Append('"'); _offset++; } else { _inQuotes = false; _quotedFieldClosed = true; } } else if (CanStartQuotedField()) { _fieldQuoted = true; _fieldStarted = true; _inQuotes = true; _quotedFieldClosed = false; _fieldBuffer.Clear(); } else { _fieldBuffer.Append(c); _fieldStarted = true; _quotedFieldClosed = false; } _lastTokenWasDelimiter = false; return true; case ',': if (!_inQuotes) { recordHasContent = true; FlushField(); _lastTokenWasDelimiter = true; return true; } break; } if ((c == '\r' || c == '\n') && !_inQuotes) { if (c == '\r' && _offset < _source.Length && _source[_offset] == '\n') { _offset++; } return false; } if (_trimUnquotedFields && _fieldQuoted && _quotedFieldClosed && char.IsWhiteSpace(c)) { _lastTokenWasDelimiter = false; return true; } recordHasContent = true; _fieldBuffer.Append(c); _fieldStarted = true; _quotedFieldClosed = false; _lastTokenWasDelimiter = false; return true; } private bool CanStartQuotedField() { if (_fieldStarted) { if (_trimUnquotedFields && !_fieldQuoted) { return FieldBufferIsWhitespace(); } return false; } return true; } private bool FieldBufferIsWhitespace() { for (int i = 0; i < _fieldBuffer.Length; i++) { if (!char.IsWhiteSpace(_fieldBuffer[i])) { return false; } } return true; } private void FlushField() { string text = _fieldBuffer.ToString(); _recordBuffer.Add((_trimUnquotedFields && !_fieldQuoted) ? text.Trim() : text); _fieldBuffer.Clear(); _fieldQuoted = false; _fieldStarted = false; _quotedFieldClosed = false; } } private static readonly char[] MustQuoteChars = new char[4] { '"', ',', '\r', '\n' }; public static string Escape(string field) { if (field == null) { return ""; } if (field.Length == 0 || field.IndexOfAny(MustQuoteChars) != -1 || (field.Length > 0 && (char.IsWhiteSpace(field[0]) || char.IsWhiteSpace(field[field.Length - 1])))) { return "\"" + field.Replace("\"", "\"\"") + "\""; } return field; } public static List> Parse(string csv) { return Parse(csv, trimUnquotedFields: false); } public static List> Parse(string csv, bool trimUnquotedFields) { return new Parser(csv, 0, trimUnquotedFields).Parse(); } public static List ParseLine(string line) { return ParseLine(line, trimUnquotedFields: false); } public static List ParseLine(string line, bool trimUnquotedFields) { return new Parser(line, 0, trimUnquotedFields).ParseLine(); } } public class InstanceCache : MonoBehaviour { private static readonly HashSet Cache; private T _instance; public static Action OnCacheAdded { get; set; } public static Action OnCacheRemoved { get; set; } static InstanceCache() { Cache = new HashSet(); } private void Awake() { _instance = GetInstance(); if (_instance != null) { object obj = _instance; Object val = (Object)((obj is Object) ? obj : null); if (val == null || Object.op_Implicit(val)) { Cache.Add(_instance); OnCacheAdded?.Invoke(_instance); return; } } throw new NullReferenceException("Failed to acquire instance."); } private void OnDestroy() { Cache.Remove(_instance); OnCacheRemoved?.Invoke(_instance); _instance = default(T); } protected virtual T GetInstance() { return ((Component)this).GetComponent(); } public static IEnumerable GetAllInstance() { return Cache.ToList(); } public static void Fill(List buffer) { if (buffer == null) { throw new ArgumentNullException("buffer"); } buffer.Clear(); buffer.AddRange(Cache); } } public enum WorldLevelMatchMode { Exact, CurrentOrHigher, Ignore } public static class Inventories { public static float CurrentWorldLevel { get { if (!((Object)(object)Game.instance != (Object)null)) { return 0f; } return Game.m_worldLevel; } } private static bool IsWorldLevelMatch(ItemData data, float worldLevel, WorldLevelMatchMode matchMode) { return matchMode switch { WorldLevelMatchMode.Exact => (float)data.m_worldLevel == worldLevel, WorldLevelMatchMode.CurrentOrHigher => (float)data.m_worldLevel >= CurrentWorldLevel, WorldLevelMatchMode.Ignore => true, _ => (float)data.m_worldLevel == worldLevel, }; } private static bool IsMatchedItem(ItemData data, string name, float worldLevel, int quality, bool isPrefabName, WorldLevelMatchMode matchMode) { if (data == null) { return false; } bool num; if (!isPrefabName) { num = data.m_shared.m_name == name; } else { if (!((Object)(object)data.m_dropPrefab != (Object)null)) { goto IL_0057; } num = ((Object)data.m_dropPrefab).name == name; } if (num && (quality < 0 || data.m_quality == quality)) { return IsWorldLevelMatch(data, worldLevel, matchMode); } goto IL_0057; IL_0057: return false; } private static void NotifyChanged(Inventory inventory) { Reflections.InvokeMethod(inventory, "Changed"); } private static int CountItems(Inventory inventory, string name, float worldLevel, int quality, bool isPrefabName = false, WorldLevelMatchMode matchMode = WorldLevelMatchMode.Exact) { return GetItems(inventory, name, worldLevel, matchMode, quality, isPrefabName).Sum((ItemData x) => x.m_stack); } private static int FindFreeStackSpace(Inventory inventory, string name, float worldLevel, int quality, bool isPrefabName) { return (from item in GetItems(inventory, name, worldLevel, WorldLevelMatchMode.Exact, quality, isPrefabName) where item.m_stack < item.m_shared.m_maxStackSize select item).Sum((ItemData item) => item.m_shared.m_maxStackSize - item.m_stack); } public static IEnumerable GetItems(Inventory inventory, string name, float worldLevel, WorldLevelMatchMode matchMode, int quality = -1, bool isPrefabName = false) { return (from data in inventory.GetAllItems() where IsMatchedItem(data, name, worldLevel, quality, isPrefabName, matchMode) select data).ToList(); } [Obsolete("Use overload with WorldLevelMatchMode parameter")] public static IEnumerable GetItems(Inventory inventory, string name, float worldLevel, int quality = -1, bool isPrefabName = false) { return GetItems(inventory, name, worldLevel, WorldLevelMatchMode.Exact, quality, isPrefabName); } public static int AddItem(Inventory inventory, GameObject prefab, int amount, int quality = -1) { if (amount <= 0) { return 0; } ItemData val = prefab.GetComponent().m_itemData.Clone(); val.m_dropPrefab = prefab; val.m_stack = Mathf.Min(amount, val.m_shared.m_maxStackSize); val.m_quality = Mathf.Clamp(quality, 1, val.m_shared.m_maxQuality); if ((Object)(object)Game.instance != (Object)null) { val.m_worldLevel = Game.m_worldLevel; } int num = CountItems(inventory, val.m_shared.m_name, val.m_worldLevel, val.m_quality); inventory.AddItem(val); return CountItems(inventory, val.m_shared.m_name, val.m_worldLevel, val.m_quality) - num; } public static int FillFreeStackSpace(Inventory from, Inventory to, string name, float worldLevel, int amount, int quality = -1, bool isPrefabName = false) { if (amount <= 0) { return 0; } int num = Mathf.Min(amount, FindFreeStackSpace(to, name, worldLevel, quality, isPrefabName)); if (num == 0) { return 0; } int num2 = 0; IEnumerable items = GetItems(to, name, worldLevel, WorldLevelMatchMode.Exact, quality, isPrefabName); foreach (ItemData item in GetItems(from, name, worldLevel, WorldLevelMatchMode.Exact, quality, isPrefabName)) { foreach (ItemData item2 in items) { if (item2.m_stack >= item2.m_shared.m_maxStackSize) { continue; } int stack = item.m_stack; int num3 = Mathf.Min(Mathf.Min(num, stack), item2.m_shared.m_maxStackSize - item2.m_stack); if (num3 != 0) { item2.m_stack += num3; num2 += num3; num -= num3; from.RemoveItem(item, num3); NotifyChanged(to); if (num == 0) { goto end_IL_00ff; } if (stack - num3 <= 0) { break; } } } continue; end_IL_00ff: break; } return num2; } public static int FillFreeStackSpace(Inventory inventory, string name, float worldLevel, int amount, int quality = -1, bool isPrefabName = false) { if (amount <= 0) { return 0; } int num = amount; int num2 = 0; foreach (ItemData item in GetItems(inventory, name, worldLevel, WorldLevelMatchMode.Exact, quality, isPrefabName)) { if (item.m_stack >= item.m_shared.m_maxStackSize) { continue; } int num3 = Mathf.Min(num, item.m_shared.m_maxStackSize - item.m_stack); if (num3 > 0) { item.m_stack += num3; num2 += num3; num -= num3; NotifyChanged(inventory); if (num == 0) { break; } } } return num2; } public static bool HaveItem(Inventory inventory, string name, float worldLevel, WorldLevelMatchMode matchMode, int amount, int quality = -1, bool isPrefabName = false) { if (amount <= 0) { return true; } int num = 0; foreach (ItemData item in GetItems(inventory, name, worldLevel, matchMode, quality, isPrefabName)) { num += item.m_stack; if (num >= amount) { return true; } } return false; } [Obsolete("Use overload with WorldLevelMatchMode parameter")] public static bool HaveItem(Inventory inventory, string name, float worldLevel, int amount, int quality = -1, bool isPrefabName = false) { return HaveItem(inventory, name, worldLevel, WorldLevelMatchMode.Exact, amount, quality, isPrefabName); } public static int RemoveItem(Inventory inventory, string name, float worldLevel, WorldLevelMatchMode matchMode, int amount, int quality = -1, bool isPrefabName = false) { if (amount <= 0) { return 0; } int num = 0; foreach (ItemData item in GetItems(inventory, name, worldLevel, matchMode, quality, isPrefabName)) { int num2 = Mathf.Min(amount, item.m_stack); inventory.RemoveItem(item, num2); num += num2; amount -= num2; if (amount == 0) { break; } } return num; } [Obsolete("Use overload with WorldLevelMatchMode parameter")] public static int RemoveItem(Inventory inventory, string name, float worldLevel, int amount, int quality = -1, bool isPrefabName = false) { return RemoveItem(inventory, name, worldLevel, WorldLevelMatchMode.Exact, amount, quality, isPrefabName); } } public static class Json { public static void AddImporter(ImporterFunc importer) { JsonMapper.RegisterImporter(importer); } public static void AddExporter(ExporterFunc exporter) { JsonMapper.RegisterExporter(exporter); } public static T Parse(string jsonText, ReaderOption option) { return JsonMapper.ToObject(new JsonReader(jsonText) { AllowComments = option.AllowComments, AllowSingleQuotedStrings = option.AllowSingleQuotedStrings, SkipNonMembers = option.SkipNonMembers }); } public static T Parse(string jsonText) { return Parse(jsonText, new ReaderOption { AllowComments = true, AllowSingleQuotedStrings = false, SkipNonMembers = true }); } public static string ToString(object obj, WriterOption option) { StringBuilder stringBuilder = new StringBuilder(); JsonMapper.ToJson(obj, new JsonWriter(stringBuilder) { IndentValue = option.IndentSize, PrettyPrint = option.Pretty }); return stringBuilder.ToString(); } public static string ToString(object obj) { return ToString(obj, new WriterOption { Pretty = false, IndentSize = 0 }); } } public struct ReaderOption { public bool AllowComments; public bool AllowSingleQuotedStrings; public bool SkipNonMembers; } public struct WriterOption { public bool Pretty; public int IndentSize; } public class L10N { private struct TranslationSource { public L10N Localization; public string Directory; } private static readonly Regex InternalNamePattern; private static readonly Dictionary TranslationCache; private static readonly Dictionary RuntimeWords; private static readonly Regex WordPattern; private const string HarmonyId = "net.eideehi.modutils.localization"; private static bool _patchesApplied; private static bool _initializePatchApplied; private static bool _setLanguagePatchApplied; private static bool _initializeMethodWarningLogged; private static bool _setLanguageMethodWarningLogged; private static bool _localizationCacheWarningLogged; private static string _currentLanguage; private static readonly List _translationSources; private readonly string _prefix; public static event Action LanguageChanged; static L10N() { _translationSources = new List(); InternalNamePattern = new Regex("^(\\$|@)(\\w|\\d|[^\\s(){}[\\]+\\-!?/\\\\&%,.:=<>])+$", RegexOptions.Compiled); TranslationCache = new Dictionary(StringComparer.OrdinalIgnoreCase); RuntimeWords = new Dictionary(StringComparer.OrdinalIgnoreCase); WordPattern = new Regex("(\\$|@)((?:\\w|\\d|[^\\s(){}[\\]+\\-!?/\\\\&%,.:=<>])+)", RegexOptions.Compiled); } public L10N(string prefix) { _prefix = prefix; } internal static void EnsurePatched() { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Expected O, but got Unknown //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Expected O, but got Unknown //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Expected O, but got Unknown if (_patchesApplied) { return; } try { Harmony val = new Harmony("net.eideehi.modutils.localization"); if (!_initializePatchApplied) { MethodInfo methodInfo = AccessTools.Method(typeof(Localization), "Initialize", (Type[])null, (Type[])null); if (methodInfo == null) { if (!_initializeMethodWarningLogged) { Debug.LogWarning((object)"[ModUtils] Localization.Initialize method not found. Auto-reload for initialization will not work until it becomes available."); _initializeMethodWarningLogged = true; } } else { val.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(L10N), "OnLocalizationInitialized", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); _initializePatchApplied = true; } } if (!_setLanguagePatchApplied) { MethodInfo methodInfo2 = AccessTools.Method(typeof(Localization), "SetLanguage", (Type[])null, (Type[])null); if (methodInfo2 == null) { if (!_setLanguageMethodWarningLogged) { Debug.LogWarning((object)"[ModUtils] Localization.SetLanguage method not found. Auto-reload for language change will not work until it becomes available."); _setLanguageMethodWarningLogged = true; } } else { val.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, new HarmonyMethod(typeof(L10N), "OnLanguageSet", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); _setLanguagePatchApplied = true; } } _patchesApplied = _initializePatchApplied && _setLanguagePatchApplied; } catch (Exception arg) { Debug.LogWarning((object)$"[ModUtils] Failed to patch Localization lifecycle methods. Auto-reload will stay disabled. {arg}"); } } private static void OnLocalizationInitialized() { try { Localization instance = Localization.instance; string text = ((instance != null) ? instance.GetSelectedLanguage() : null); if (!string.IsNullOrEmpty(text)) { HandleLanguageChange(text); } } catch (Exception arg) { Debug.LogError((object)$"[ModUtils] OnLocalizationInitialized error: {arg}"); } } private static void OnLanguageSet(string language) { try { if (!string.IsNullOrEmpty(language)) { HandleLanguageChange(language); } } catch (Exception arg) { Debug.LogError((object)$"[ModUtils] OnLanguageSet error: {arg}"); } } private static void HandleLanguageChange(string language) { ApplyLanguageChange(language, fireLanguageChanged: true); } public static string SyncCurrentLanguage() { EnsurePatched(); try { Localization instance = Localization.instance; if (instance == null) { return null; } string selectedLanguage = instance.GetSelectedLanguage(); if (string.IsNullOrEmpty(selectedLanguage)) { return null; } ApplyLanguageChange(selectedLanguage, fireLanguageChanged: false); return selectedLanguage; } catch (Exception arg) { Debug.LogError((object)$"[ModUtils] SyncCurrentLanguage failed: {arg}"); return null; } } private static void ApplyLanguageChange(string language, bool fireLanguageChanged) { if (!string.IsNullOrEmpty(language) && !string.Equals(language, _currentLanguage, StringComparison.OrdinalIgnoreCase)) { ReloadTranslations(language); _currentLanguage = language; RefreshConfigurationMetadata(); RefreshDefaultDrawerTranslations(); if (fireLanguageChanged) { FireLanguageChanged(language); } } } private static void RefreshConfigurationMetadata() { try { Configuration.RefreshAllLocalizedMetadata(); } catch (Exception arg) { Debug.LogError((object)$"[ModUtils] Failed to refresh localized config metadata: {arg}"); } } private static void RefreshDefaultDrawerTranslations() { try { ConfigurationCustomDrawer.RefreshDefaultTranslations(); } catch (Exception arg) { Debug.LogError((object)$"[ModUtils] Failed to refresh custom drawer translations: {arg}"); } } private static void ReloadTranslations(string language) { TranslationCache.Clear(); foreach (TranslationSource translationSource in _translationSources) { try { new TranslationsLoader(translationSource.Localization).LoadTranslations(translationSource.Directory, language); } catch (Exception arg) { Debug.LogError((object)$"[ModUtils] Failed to reload translations from {translationSource.Directory}: {arg}"); } } Localization localization = TryGetLocalization(); foreach (KeyValuePair runtimeWord in RuntimeWords) { TranslationCache[runtimeWord.Key] = runtimeWord.Value; AddWordToLocalization(localization, runtimeWord.Key, runtimeWord.Value); } } private static void FireLanguageChanged(string language) { Action languageChanged = L10N.LanguageChanged; if (languageChanged == null) { return; } Delegate[] invocationList = languageChanged.GetInvocationList(); foreach (Delegate @delegate in invocationList) { try { ((Action)@delegate)(language); } catch (Exception arg) { Debug.LogError((object)$"[ModUtils] LanguageChanged handler error: {arg}"); } } } public void AddTranslationDirectory(string directory) { EnsurePatched(); _translationSources.Add(new TranslationSource { Localization = this, Directory = directory }); new TranslationsLoader(this).LoadTranslations(directory, DetectCurrentLanguage()); Localization localization = TryGetLocalization(); foreach (KeyValuePair runtimeWord in RuntimeWords) { TranslationCache[runtimeWord.Key] = runtimeWord.Value; AddWordToLocalization(localization, runtimeWord.Key, runtimeWord.Value); } } private static string DetectCurrentLanguage() { if (_currentLanguage != null) { return _currentLanguage; } try { Localization instance = Localization.instance; string text = ((instance != null) ? instance.GetSelectedLanguage() : null); if (!string.IsNullOrEmpty(text)) { return text; } } catch (Exception) { } return "English"; } internal static Localization TryGetLocalization() { try { Localization instance = Localization.instance; if (instance == null) { return null; } return string.IsNullOrEmpty(instance.GetSelectedLanguage()) ? null : instance; } catch (Exception) { return null; } } private static string InvokeTranslate(string word) { Localization val = TryGetLocalization(); TranslationCache.TryGetValue(word, out var value); if (val == null) { return value ?? word; } string text = Reflections.InvokeMethod(val, "Translate", new object[1] { word }); if (text == null || IsMissingTranslation(word, text)) { return value ?? word; } return text; } private static bool IsMissingTranslation(string word, string localized) { if (!string.Equals(localized, word, StringComparison.Ordinal)) { return string.Equals(localized, "[" + word + "]", StringComparison.Ordinal); } return true; } private static string InvokeInsertWordsFallback(string text, IReadOnlyList words) { if (string.IsNullOrEmpty(text)) { return text; } string text2 = text; for (int i = 0; i < words.Count; i++) { text2 = text2.Replace($"${i + 1}", words[i] ?? ""); } return text2; } private static string InvokeInsertWords(string text, string[] words) { if (string.IsNullOrEmpty(text)) { return text; } Localization val = TryGetLocalization(); if (val == null) { return InvokeInsertWordsFallback(text, words); } return Reflections.InvokeMethod(val, "InsertWords", new object[2] { text, words }); } private static void InvokeAddWord(string key, string word) { TranslationCache[key] = word; AddWordToLocalization(TryGetLocalization(), key, word); } private static void InvokeAddRuntimeWord(string key, string word) { RuntimeWords[key] = word; TranslationCache[key] = word; AddWordToLocalization(TryGetLocalization(), key, word); } private static void AddWordToLocalization(Localization localization, string key, string word) { if (localization != null) { Reflections.InvokeMethod(localization, "AddWord", key, word); EvictLocalizationCache(localization); } } private static void EvictLocalizationCache(Localization localization) { try { object field = Reflections.GetField(localization, "m_cache"); if (field != null) { Reflections.InvokeMethod(field, "EvictAll"); } } catch (Exception arg) { if (!_localizationCacheWarningLogged) { Debug.LogWarning((object)$"[ModUtils] Failed to evict Localization cache after adding a word. Game-localized text may stay stale until the next language reload. {arg}"); _localizationCacheWarningLogged = true; } } } internal static string GetTranslationKey(string prefix, string internalName) { if (string.IsNullOrEmpty(internalName)) { return ""; } return internalName[0] switch { '$' => internalName.Substring(1), '@' => prefix + "_" + internalName.Substring(1), _ => internalName, }; } internal static string Translate(string prefix, string word) { return InvokeTranslate(GetTranslationKey(prefix, word)); } public static bool IsInternalName(string text) { if (!string.IsNullOrEmpty(text)) { return InternalNamePattern.IsMatch(text); } return false; } private string GetTranslationKey(string internalName) { return GetTranslationKey(_prefix, internalName); } public void AddWord(string key, string word) { InvokeAddRuntimeWord(GetTranslationKey(key), word); } internal void AddFileWord(string key, string word) { InvokeAddWord(GetTranslationKey(key), word); } public string Translate(string word) { return InvokeTranslate(GetTranslationKey(word)); } public string TranslateInternalName(string internalName) { if (IsInternalName(internalName)) { return InvokeTranslate(GetTranslationKey(internalName)); } return internalName; } public string Localize(string text) { if (string.IsNullOrEmpty(text)) { return text; } StringBuilder stringBuilder = new StringBuilder(); int num = 0; foreach (Match item in WordPattern.Matches(text)) { GroupCollection groups = item.Groups; string word = ((groups[1].Value == "@") ? (_prefix + "_" + groups[2].Value) : groups[2].Value); stringBuilder.Append(text.Substring(num, groups[0].Index - num)); stringBuilder.Append(InvokeTranslate(word)); num = groups[0].Index + groups[0].Value.Length; } stringBuilder.Append(text.Substring(num)); return stringBuilder.ToString(); } public string Localize(string text, params object[] args) { object[] array = args ?? new object[0]; return InvokeInsertWords(Localize(text), Array.ConvertAll(array, (object arg) => (arg != null) ? ((!(arg is string internalName)) ? arg.ToString() : TranslateInternalName(internalName)) : "")); } public string LocalizeTextOnly(string text, params object[] args) { object[] array = args ?? new object[0]; return InvokeInsertWords(Localize(text), Array.ConvertAll(array, delegate(object arg) { object obj; if (arg != null) { obj = arg as string; if (obj == null) { return arg.ToString(); } } else { obj = ""; } return (string)obj; })); } } public class TranslationsLoader { private static readonly string DefaultLanguage; private static readonly string JsonFilePattern; private readonly L10N _localization; private Dictionary _cache; private Logger _logger; static TranslationsLoader() { DefaultLanguage = "English"; JsonFilePattern = "*.json"; } public TranslationsLoader(L10N localization) { _localization = localization; } public void SetDebugLogger(Logger logger) { _logger = logger; } private bool LoadAllFile(string directory, string filePattern, string language, Func loading) { _logger?.Debug("Load translation files for " + language + " from directory: [directory: " + directory + ", file pattern: " + filePattern + "]"); return Directory.EnumerateFiles(directory, filePattern, SearchOption.AllDirectories).Count((string path) => loading(path, language)) > 0; } public void LoadTranslations(string languagesDir, string language) { _cache = new Dictionary(); if (!Directory.Exists(languagesDir)) { _logger?.Error("Directory does not exist: " + languagesDir); return; } if (language != DefaultLanguage && !LoadAllFile(languagesDir, JsonFilePattern, DefaultLanguage, ReadJsonFile)) { _logger?.Warning("Directory does not contain a translation file for the default language: " + languagesDir); } if (!LoadAllFile(languagesDir, JsonFilePattern, language, ReadJsonFile)) { _logger?.Warning("Directory does not contain a translation file for the " + language + ": " + languagesDir); } _cache = null; } public void LoadTranslations(string languagesDir) { string text; try { Localization instance = Localization.instance; text = ((instance != null) ? instance.GetSelectedLanguage() : null); } catch (Exception) { text = null; } LoadTranslations(languagesDir, string.IsNullOrEmpty(text) ? DefaultLanguage : text); } private bool ReadJsonFile(string path, string language) { if (!_cache.TryGetValue(path, out var value)) { try { value = Json.Parse(File.ReadAllText(path)); _cache.Add(path, value); } catch (Exception arg) { _logger?.Error($"Failed to read Json file\n{arg}"); _cache.Add(path, default(TranslationsFile)); return false; } } if (!string.Equals(value.language, language, StringComparison.OrdinalIgnoreCase)) { return false; } _logger?.Debug("Load translations: " + path); if (value.translations == null) { _logger?.Warning("Translation file does not contain translations: " + path); return true; } foreach (KeyValuePair translation in value.translations) { _localization.AddFileWord(translation.Key, translation.Value); } return true; } } [Serializable] public struct TranslationsFile { public string language; public Dictionary translations; } public class Logger { private readonly Func _isEnabled; private readonly ManualLogSource _logger; public Logger(ManualLogSource logger, Func isEnabled) { _logger = logger; _isEnabled = isEnabled; } private void Log(LogLevel level, string message) { //IL_0006: 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) if (_isEnabled(level)) { _logger.Log(level, (object)message); } } private void Log(LogLevel level, Func message) { //IL_0006: 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) if (_isEnabled(level)) { _logger.Log(level, (object)message()); } } public void Fatal(Func message) { Log((LogLevel)1, message); } public void Fatal(string message) { Log((LogLevel)1, message); } public void Error(Func message) { Log((LogLevel)2, message); } public void Error(string message) { Log((LogLevel)2, message); } public void Warning(Func message) { Log((LogLevel)4, message); } public void Warning(string message) { Log((LogLevel)4, message); } public void Info(Func message) { Log((LogLevel)16, message); } public void Info(string message) { Log((LogLevel)16, message); } public void Message(Func message) { Log((LogLevel)8, message); } public void Message(string message) { Log((LogLevel)8, message); } public void Debug(Func message) { Log((LogLevel)32, message); } public void Debug(string message) { Log((LogLevel)32, message); } } public abstract class ObjectNode : MonoBehaviour where TNode : ObjectNode where TNetwork : ObjectNetwork { protected static readonly HashSet ObjectNodes; private TNode This => (TNode)this; public TNetwork Network { get; set; } static ObjectNode() { ObjectNodes = new HashSet(); } protected virtual void Awake() { ObjectNodes.Add(This); ((MonoBehaviour)this).Invoke("NetworkConstruction", Random.Range(1f, 2f)); } protected virtual void OnDestroy() { ObjectNodes.Remove(This); Network?.RemoveNode(This); Network = null; } protected abstract TNetwork CreateNetwork(); protected abstract bool IsConnectable(TNode other); private void NetworkConstruction() { foreach (TNode item in ObjectNodes.Where(IsConnectable)) { if (Network == item.Network) { continue; } if (Network == null) { Network = item.Network; Network.AddNode(This); continue; } if (item.Network == null) { item.Network = Network; item.Network.AddNode(item); continue; } TNetwork obj = ((Network.NodeCount >= item.Network.NodeCount) ? item.Network : Network); TNetwork network = ((Network.NodeCount >= item.Network.NodeCount) ? Network : item.Network); foreach (TNode allNode in obj.GetAllNodes()) { allNode.Network.RemoveNode(allNode); allNode.Network = network; allNode.Network.AddNode(allNode); } } if (Network == null) { Network = CreateNetwork(); Network.AddNode(This); } } } public class ObjectNetwork where TNode : ObjectNode where TNetwork : ObjectNetwork { private readonly HashSet _nodes; protected Action> OnNodeChanged { get; set; } public bool IsDirty { get; private set; } public int NodeCount => _nodes.Count; protected ObjectNetwork() { _nodes = new HashSet(); } public IEnumerable EnumerateNodes() { return _nodes; } public IEnumerable GetAllNodes() { return _nodes.ToList(); } public void AddNode(TNode node) { if (_nodes.Add(node)) { IsDirty = true; } } public void RemoveNode(TNode node) { if (_nodes.Remove(node)) { IsDirty = true; } } public void Update() { if (IsDirty) { OnNodeChanged?.Invoke(GetAllNodes()); IsDirty = false; } } } public static class Objects { private static readonly ConditionalWeakTable ZNetViewCache; private static readonly ConditionalWeakTable NameCache; private const string HoverableMarker = "\u0001HOVERABLE"; static Objects() { ZNetViewCache = new ConditionalWeakTable(); NameCache = new ConditionalWeakTable(); } public static string GetPrefabName(GameObject gameObject) { return Utils.GetPrefabName(gameObject); } public static string GetName(Component component) { if (!Object.op_Implicit((Object)(object)component)) { return ""; } if (NameCache.TryGetValue(component, out var value)) { if ((object)value == "\u0001HOVERABLE") { Hoverable component2 = component.GetComponent(); string text = ((component2 != null) ? component2.GetHoverName() : null); if (string.IsNullOrEmpty(text)) { return Utils.GetPrefabName(component.gameObject); } return text; } return value; } string text2 = (from x in ((object)component).GetType().GetFields(AccessTools.all) where x.Name == "m_name" && x.FieldType == typeof(string) select x.GetValue(component) as string).FirstOrDefault(); if (!string.IsNullOrEmpty(text2)) { NameCache.Add(component, text2); return text2; } Hoverable component3 = component.GetComponent(); if (component3 != null) { HoverText val = (HoverText)(object)((component3 is HoverText) ? component3 : null); if (val != null) { text2 = val.m_text; if (!string.IsNullOrEmpty(text2)) { NameCache.Add(component, text2); return text2; } } else { text2 = component3.GetHoverName(); if (!string.IsNullOrEmpty(text2)) { NameCache.Add(component, "\u0001HOVERABLE"); return text2; } } } text2 = Utils.GetPrefabName(component.gameObject); NameCache.Add(component, text2); return text2; } public static bool GetZNetView(Component component, out ZNetView zNetView) { if (!Object.op_Implicit((Object)(object)component)) { zNetView = null; return false; } if (ZNetViewCache.TryGetValue(component, out zNetView)) { return Object.op_Implicit((Object)(object)zNetView); } zNetView = (from x in ((object)component).GetType().GetFields(AccessTools.all) where x.Name == "m_nview" && x.FieldType == typeof(ZNetView) select x).Select(delegate(FieldInfo x) { object? value = x.GetValue(component); return (ZNetView)((value is ZNetView) ? value : null); }).FirstOrDefault() ?? component.GetComponent(); if ((Object)(object)zNetView == (Object)null) { return false; } ZNetViewCache.Add(component, zNetView); return true; } public static bool GetZdoid(Component component, out ZDOID id) { //IL_0020: 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_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) id = (GetZNetView(component, out var zNetView) ? zNetView.GetZDO() : null)?.m_uid ?? ZDOID.None; return id != ZDOID.None; } public static bool HasValidOwnership(ZNetView zNetView) { if ((Object)(object)zNetView != (Object)null && zNetView.GetZDO() != null && zNetView.IsValid()) { return zNetView.IsOwner(); } return false; } public static bool HasValidOwnership(Component component) { ZNetView zNetView; return HasValidOwnership(component, out zNetView); } public static bool HasValidOwnership(Component component, out ZNetView zNetView) { if (GetZNetView(component, out zNetView)) { return HasValidOwnership(zNetView); } return false; } public static float Distance(Component obj1, Component obj2) { //IL_0006: 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) return Vector3.Distance(obj1.transform.position, obj2.transform.position); } public static List<(Collider collider, T obj, float distance)> GetInsideSphere(Vector3 origin, float radius, Func convertor, Collider[] buffer, int layerMask = -1) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) List<(Collider, T, float)> list = new List<(Collider, T, float)>(); int num = Physics.OverlapSphereNonAlloc(origin, radius, buffer, layerMask); for (int i = 0; i < num; i++) { Collider val = buffer[i]; T val2 = convertor(val); if (val2 != null) { list.Add((val, val2, Vector3.Distance(origin, ((Component)val).transform.position))); } } return list; } public static List<(Collider collider, T obj, float distance)> GetInsideSphere(Vector3 origin, float radius, Func convertor, int bufferSize = 128, int layerMask = -1) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return GetInsideSphere(origin, radius, convertor, (Collider[])(object)new Collider[bufferSize], layerMask); } } public static class Reflections { public static TR InvokeStaticMethod(string methodName, params object[] args) { return Traverse.Create().Method(methodName, args).GetValue(args); } public static void InvokeStaticMethod(string methodName, params object[] args) { Traverse.Create().Method(methodName, args).GetValue(args); } public static TR InvokeStaticMethod(string methodName) { return Traverse.Create().Method(methodName, Array.Empty()).GetValue(); } public static void InvokeStaticMethod(string methodName) { Traverse.Create().Method(methodName, Array.Empty()).GetValue(); } public static T InvokeMethod(object instance, string methodName, params object[] args) { return Traverse.Create(instance).Method(methodName, args).GetValue(args); } public static void InvokeMethod(object instance, string methodName, params object[] args) { Traverse.Create(instance).Method(methodName, args).GetValue(args); } public static T InvokeMethod(object instance, string methodName) { return Traverse.Create(instance).Method(methodName, Array.Empty()).GetValue(); } public static void InvokeMethod(object instance, string methodName) { Traverse.Create(instance).Method(methodName, Array.Empty()).GetValue(); } public static TType GetStaticField(string fieldName) { return Traverse.Create().Field(fieldName).Value; } public static TType SetStaticField(string fieldName, TType value) { return Traverse.Create().Field(fieldName).Value = value; } public static T GetField(object instance, string fieldName) { return Traverse.Create(instance).Field(fieldName).Value; } public static void SetField(object instance, string fieldName, T value) { Traverse.Create(instance).Field(fieldName).Value = value; } } public class SpriteLoader { private static readonly Dictionary TextureCache; private Logger _logger; static SpriteLoader() { TextureCache = new Dictionary(); } private static Sprite CreateSprite(Texture2D texture, int width, int height) { //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) return Sprite.Create(texture, new Rect(0f, 0f, (float)width, (float)height), Vector2.zero); } public static string GetTextureFileName(Sprite sprite) { using (IEnumerator> enumerator = TextureCache.Where((KeyValuePair pair) => (Object)(object)pair.Value == (Object)(object)sprite.texture).GetEnumerator()) { if (enumerator.MoveNext()) { return Path.GetFileName(enumerator.Current.Key); } } return ""; } public void SetDebugLogger(Logger logger) { _logger = logger; } public Sprite Load(string texturePath, int width, int height) { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Expected O, but got Unknown if (!File.Exists(texturePath)) { return null; } if (TextureCache.TryGetValue(texturePath, out var value)) { if (!((Object)(object)value != (Object)null)) { return null; } return CreateSprite(value, width, height); } try { _logger?.Info("Try to create sprite: " + texturePath); Texture2D val = new Texture2D(0, 0); ImageConversion.LoadImage(val, File.ReadAllBytes(texturePath)); TextureCache.Add(texturePath, val); return CreateSprite(val, width, height); } catch (Exception arg) { _logger?.Error($"Failed to create sprite: {texturePath}\n{arg}"); TextureCache.Add(texturePath, null); return null; } } } } namespace Automatics { [BepInPlugin("net.eidee.valheim.automatics", "Automatics", "1.6.0")] public class UnityPlugin : BaseUnityPlugin { private const string ModId = "net.eidee.valheim.automatics"; private const string ModName = "Automatics"; private const string ModVersion = "1.6.0"; private void Awake() { Automatics.Initialize((BaseUnityPlugin)(object)this, ((BaseUnityPlugin)this).Logger); } private void FixedUpdate() { if (!((Object)(object)Player.m_localPlayer != (Object)null) && Object.op_Implicit((Object)(object)ZNet.instance) && ZNet.instance.IsServer()) { Hooks.OnDedicatedServerFixedUpdate?.Invoke(Time.fixedDeltaTime); } } } internal static class Automatics { public const string L10NPrefix = "automatics"; private static string _modLocation; private static string _guid; private static List _allResourcesDirectory; private static bool _runtimeInitialized; public static BaseUnityPlugin Plugin { get; private set; } public static Logger Logger { get; private set; } public static ManualLogSource LogSource { get; private set; } public static L10N L10N { get; private set; } private static IEnumerable GetAllResourcesDirectory() { if (_allResourcesDirectory != null) { return _allResourcesDirectory; } _allResourcesDirectory = new List { _modLocation }; string pluginPath = Paths.PluginPath; if (!Directory.Exists(pluginPath)) { return _allResourcesDirectory; } string[] directories = Directory.GetDirectories(pluginPath); foreach (string text in directories) { if (File.Exists(Path.Combine(text, "automatics-child-mod"))) { _allResourcesDirectory.Add(text); } else if (File.Exists(Path.Combine(text, "automatics-resources-marker"))) { _allResourcesDirectory.Add(text); } } return _allResourcesDirectory; } private static void InitializeModules(Assembly assembly) { foreach (var item2 in from x in ((IEnumerable)AccessTools.GetTypesFromAssembly(assembly)).SelectMany((Func>)AccessTools.GetDeclaredMethods) select (x, x.GetCustomAttributes(typeof(AutomaticsInitializerAttribute), inherit: false).OfType().FirstOrDefault()) into x where x.Item2 != null orderby x.Item2.Order select x) { MethodInfo item = item2.Item1; try { item.Invoke(null, new object[0]); } catch (Exception arg) { Logger.Error($"Error while initializing {item.Name}\n{arg}"); } } } public static IEnumerable GetAllResourcePath(string pathname) { return from x in GetAllResourcesDirectory() select Path.Combine(x, pathname); } public static string GetHarmonyId(string moduleName) { return _guid + "." + moduleName; } public static void Initialize(BaseUnityPlugin plugin, ManualLogSource logger) { //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Expected O, but got Unknown Plugin = plugin; LogSource = logger; Logger = new Logger(logger, Config.IsLogEnabled); _modLocation = Path.GetDirectoryName(Plugin.Info.Location) ?? ""; _guid = Plugin.Info.Metadata.GUID; Logger.Debug("Mod location: " + _modLocation); ConfigMigration.Migration(Plugin.Config); ValheimObject.Initialize(GetAllResourcePath("Data")); Harmony val = new Harmony(_guid); L10N = new L10N("automatics"); foreach (string item in GetAllResourcePath("Languages")) { L10N.AddTranslationDirectory(item); } L10N.LanguageChanged += InitializeRuntime; InitializeRuntime(L10N.SyncCurrentLanguage() ?? "English"); Hooks.OnInitTerminal = (Action)Delegate.Combine(Hooks.OnInitTerminal, new Action(Commands.Register)); val.PatchAll(typeof(Patches)); } public static void InitializeRuntime(string language) { if (_runtimeInitialized) { ConfigurationManagerBridge.Refresh(); return; } Config.Initialize(Plugin.Config); Plugin.Config.Save(); InitializeModules(Assembly.GetExecutingAssembly()); Plugin.Config.Save(); ValheimObject.PostInitialize(); _runtimeInitialized = true; ConfigurationManagerBridge.Refresh(); } } [AttributeUsage(AttributeTargets.Method)] [MeansImplicitUse] public class AutomaticsInitializerAttribute : Attribute { public int Order { get; } public AutomaticsInitializerAttribute(int order = 0) { Order = order; } } internal static class Commands { public static void Register() { new ShowCommands().Register(); new PrintNames().Register(); new PrintObjects().Register(); new RemoveMapPins().Register(); } } internal static class Config { private const int NexusID = 1700; private static ConfigEntry _logEnabled; private static ConfigEntry _allowedLogLevel; public static bool LogEnabled => _logEnabled.Value; public static LogLevel AllowedLogLevel => _allowedLogLevel.Value; public static bool Initialized { get; private set; } public static Configuration Instance { get; private set; } public static bool IsLogEnabled(LogLevel level) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: 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_0016: Invalid comparison between Unknown and I4 if (Initialized) { if (LogEnabled) { return (AllowedLogLevel & level) > 0; } return false; } return true; } public static ConfigEntry> BindCustomValheimObject(this Configuration config, string key, ValheimObject obj) { ConfigEntry> entry = config.Bind(key, new List()); if (entry.Value.Any()) { obj.RegisterCustom(entry.Value); } entry.SettingChanged += delegate { obj.RegisterCustom(entry.Value); }; return entry; } public static ConfigEntry BindValheimObjectList(this Configuration config, string key, ValheimObject obj, IEnumerable defaults = null, IEnumerable includes = null, IEnumerable excludes = null) { List list = new List(); list.AddRange(defaults ?? (from x in obj.GetAllElements() select x.identifier)); if (includes != null) { list.RemoveAll((string x) => !includes.Contains(x)); } if (excludes != null) { list.RemoveAll(excludes.Contains); } return config.Bind(key, new StringList(list), null, delegate(ConfigurationManagerAttributes x) { x.CustomDrawer = ConfigurationCustomDrawer.MultiSelect(() => from y in obj.GetAllElements() select y.identifier, (string identifier) => (!obj.GetName(identifier, out var name)) ? identifier : Automatics.L10N.TranslateInternalName(name)); }); } public static void Initialize(ConfigFile config) { if (!Initialized) { Instance = new Configuration(config, Automatics.L10N); Instance.ChangeSection("hidden"); Instance.Bind("NexusID", 1700, null, delegate(ConfigurationManagerAttributes x) { x.Browsable = false; x.ReadOnly = true; }); Instance.ChangeSection("system"); _logEnabled = Instance.Bind("enable_logging", defaultValue: false); _allowedLogLevel = Instance.Bind("log_level_to_allow_logging", (LogLevel)15); Instance.ChangeSection("general"); Instance.BindCustomValheimObject("custom_animal", ValheimObject.Animal); Instance.BindCustomValheimObject("custom_dungeon", ValheimObject.Dungeon); Instance.BindCustomValheimObject("custom_flora", ValheimObject.Flora); Instance.BindCustomValheimObject("custom_mineral", ValheimObject.Mineral); Instance.BindCustomValheimObject("custom_monster", ValheimObject.Monster); Instance.BindCustomValheimObject("custom_spawner", ValheimObject.Spawner); Instance.BindCustomValheimObject("custom_spot", ValheimObject.Spot); Initialized = true; } } } public enum AutomaticsModule { [LocalizedDescription("automatics", "@message_module_enabled")] Enabled, [LocalizedDescription("automatics", "@message_module_disabled")] Disabled } public enum Message { [LocalizedDescription("automatics", "@message_none")] None, [LocalizedDescription("automatics", "@message_center")] Center, [LocalizedDescription("automatics", "@message_top_left")] TopLeft } internal static class ConfigMigration { private class Config { public int Offset; public string Category; public string Key; public string Value; } private delegate bool Operation(string category, List lines, int begin, int end); private readonly struct Version : IComparable { private readonly int _major; private readonly int _minor; private readonly int _patch; public Version(int major, int minor, int patch) { _major = major; _minor = minor; _patch = patch; } public override string ToString() { return $"v{_major}.{_minor}.{_patch}"; } public int CompareTo(Version other) { if (_major != other._major) { return _major.CompareTo(other._major); } if (_minor == other._minor) { return _patch.CompareTo(other._patch); } return _minor.CompareTo(other._minor); } public static bool operator >(Version a, Version b) { return a.CompareTo(b) > 0; } public static bool operator <(Version a, Version b) { return a.CompareTo(b) < 0; } } private static readonly Regex VersionPattern; private static readonly char[] KeyValueSeparator; private static readonly Dictionary> ConfigCache; static ConfigMigration() { VersionPattern = new Regex("v(\\d+)\\.(\\d+)\\.(\\d+)$", RegexOptions.Compiled); KeyValueSeparator = new char[1] { '=' }; ConfigCache = new Dictionary>(); } private static Operation RenameCategory(string newCategory) { return delegate(string category, List lines, int begin, int end) { string text = lines[begin]; lines[begin] = newCategory; Automatics.Logger.Message("Rename category: " + text + " => " + newCategory); return true; }; } private static Operation RemoveConfig(string key) { return delegate(string category, List lines, int begin, int end) { foreach (Config item in FindConfig(category, key, lines, begin, end)) { string key2 = item.Key; item.Key = ""; UpdateConfig(item, lines); Automatics.Logger.Message("Remove config: " + category + " " + key2); } return true; }; } private static Operation RenameConfig(string key, string newKey) { return delegate(string category, List lines, int begin, int end) { foreach (Config item in FindConfig(category, key, lines, begin, end)) { string key2 = item.Key; item.Key = (GetMatcher(key).IsRegex ? Regex.Replace(key, key, newKey) : newKey); UpdateConfig(item, lines); Automatics.Logger.Message("Rename config: " + category + " " + key2 + " => " + item.Key); } return true; }; } private static Operation ReplaceValue(string key, string value, string newValue) { return delegate(string category, List lines, int begin, int end) { foreach (Config item in from x in FindConfig(category, key, lines, begin, end) where string.Equals(x.Value, value, StringComparison.OrdinalIgnoreCase) select x) { string value2 = item.Value; item.Value = newValue; UpdateConfig(item, lines); Automatics.Logger.Message("Replace value: " + category + " " + key + " " + value2 + " => " + newValue); } return true; }; } private static Operation AppendValues(string key, string[] valuesToAppend) { return delegate(string category, List lines, int begin, int end) { List list = FindConfig(category, key, lines, begin, end).ToList(); if (!list.Any()) { return false; } foreach (Config item2 in list) { string text = item2.Value ?? ""; List list2 = (string.IsNullOrWhiteSpace(text) ? new List() : (from x in Csv.ParseLine(text) where !string.IsNullOrEmpty(x) select x).ToList()); HashSet hashSet = new HashSet(list2, StringComparer.Ordinal); List list3 = new List(); string[] array = valuesToAppend; foreach (string text2 in array) { if (!string.IsNullOrWhiteSpace(text2)) { string item = text2.Trim(); if (hashSet.Add(item)) { list2.Add(item); list3.Add(item); } } } if (list3.Count != 0) { item2.Value = string.Join(", ", list2.Select(Csv.Escape)); UpdateConfig(item2, lines); Automatics.Logger.Message("Append values: " + category + " " + key + " += [" + string.Join(", ", list3) + "]"); } } return true; }; } private static IEnumerable FindConfig(string category, string key, List lines, int begin = 0, int end = int.MaxValue) { (bool IsRegex, string Pattern) matcher = GetMatcher(key); if (ConfigCache.TryGetValue(category, out var value)) { return value.Where((Config x) => x.Category == category && IsMatch(x.Key, matcher)); } end = Mathf.Min(end, lines.Count); begin = Mathf.Clamp(begin, 0, end); value = new List(0); string text = ""; int i; for (i = begin; i < end; i++) { string text2 = lines[i]; if (text2.StartsWith("#")) { continue; } if (Regex.IsMatch(text2, "^\\[[\\w\\d_]+\\]$")) { text = text2; if (!ConfigCache.TryGetValue(text, out value)) { value = new List(); ConfigCache[text] = value; } } else if (!value.Any((Config x) => x.Offset == i)) { string[] array = text2.Split(KeyValueSeparator, 2, StringSplitOptions.None); if (array.Length == 2) { Config item = new Config { Offset = i, Category = text, Key = array[0].Trim(), Value = array[1].Trim() }; value.Add(item); } } } if (ConfigCache.TryGetValue(category, out value)) { return value.Where((Config x) => x.Category == category && IsMatch(x.Key, matcher)); } Automatics.Logger.Warning("No config matching condition exists: " + category + " / " + key); return Array.Empty(); } private static void UpdateConfig(Config config, List lines) { if (config.Offset >= 0 || config.Offset < lines.Count) { if (string.IsNullOrEmpty(config.Key)) { lines[config.Offset] = ""; } else { lines[config.Offset] = config.Key + " = " + config.Value; } } } private static (bool IsRegex, string Pattern) GetMatcher(string pattern) { if (string.IsNullOrEmpty(pattern)) { return (false, ""); } if (!pattern.StartsWith("r/")) { return (false, pattern); } return (true, pattern.Substring(2)); } private static bool IsMatch(string value, (bool IsRegex, string Pattern) matcher) { if (!matcher.IsRegex) { if (!string.IsNullOrEmpty(matcher.Pattern)) { return string.Equals(value, matcher.Pattern, StringComparison.OrdinalIgnoreCase); } return false; } return Regex.IsMatch(value, matcher.Pattern, RegexOptions.IgnoreCase); } public static void Migration(ConfigFile config) { string configFilePath = config.ConfigFilePath; if (!File.Exists(configFilePath)) { return; } List list = File.ReadAllLines(configFilePath).ToList(); if (list.Any()) { bool flag = false; Version version = ParseVersion(list[0]); Version version2 = new Version(1, 3, 0); if (version < version2) { Automatics.Logger.Message($"Migrating config from {version} to {version2}"); flag = true; MigrationFor130(list); } version2 = new Version(1, 4, 0); if (version < version2) { Automatics.Logger.Message($"Migrating config from {version} to {version2}"); flag = true; MigrationFor140(list); } version2 = new Version(1, 4, 5); if (version < version2) { Automatics.Logger.Message($"Migrating config from {version} to {version2}"); flag = true; MigrationFor145(list); } version2 = new Version(1, 6, 0); if (version < version2) { Automatics.Logger.Message($"Migrating config from {version} to {version2}"); flag = true; MigrationFor160(list); } if (flag) { File.WriteAllText(configFilePath, string.Join(Environment.NewLine, list), Encoding.UTF8); config.Reload(); } } } private static void MigrationFor130(List lines) { Migration(lines, new Dictionary> { { "[logging]", new List { RenameCategory("[system]"), RenameConfig("logging_enabled", "enable_logging"), RenameConfig("allowed_log_level", "log_level_to_allow_logging") } }, { "[automatic_door]", new List { RenameConfig("automatic_door_enabled", "enable_automatic_door"), RenameConfig("player_search_radius_to_open", "distance_for_automatic_opening"), RenameConfig("player_search_radius_to_close", "distance_for_automatic_closing"), RenameConfig("toggle_automatic_door_enabled_key", "automatic_door_enable_disable_toggle") } }, { "[automatic_map_pinning]", new List { RenameCategory("[automatic_mapping]"), RenameConfig("automatic_map_pinning_enabled", "enable_automatic_mapping"), RenameConfig("allow_pinning_vein", "allow_pinning_deposit"), RenameConfig("allow_pinning_vein_custom", "allow_pinning_deposit_custom"), RenameConfig("ignore_tamed_animals", "not_pinning_tamed_animals"), RenameConfig("in_ground_veins_need_wishbone", "need_to_equip_wishbone_for_underground_deposits") } }, { "[automatic_processing]", new List { RenameConfig("automatic_processing_enabled", "enable_automatic_processing"), RenameConfig("r/^([\\w_]+)_allow_automatic_processing", "allow_processing_by_$1"), RenameConfig("r/^([\\w_]+)_container_search_range", "container_search_range_by_$1"), RenameConfig("r/^([\\w_]+)_material_count_that_suppress_automatic_process", "$1_material_count_of_suppress_processing"), RenameConfig("r/^([\\w_]+)_fuel_count_that_suppress_automatic_process", "$1_fuel_count_of_suppress_processing"), RenameConfig("r/^([\\w_]+)_product_count_that_suppress_automatic_store", "$1_product_count_of_suppress_processing") } }, { "[automatic_feeding]", new List { RenameConfig("automatic_feeding_enabled", "enable_automatic_feeding"), RenameConfig("need_close_to_eat_the_feed", "need_get_close_to_eat_the_feed"), RenameConfig("automatic_repair_enabled", "enable_automatic_repair") } } }); } private static void MigrationFor140(List lines) { Migration(lines, new Dictionary> { { "[automatic_door]", new List { RemoveConfig("allow_automatic_door_custom"), ReplaceValue("allow_automatic_door", "All", "WoodDoor, WoodGate, IronGate, DarkwoodGate, WoodShutter") } }, { "[automatic_mapping]", new List { RenameConfig("dynamic_object_search_range", "dynamic_object_mapping_range"), RenameConfig("static_object_search_range", "static_object_mapping_range"), RenameConfig("location_search_range", "location_mapping_range"), RenameConfig("allow_pinning_deposit", "allow_pinning_mineral"), RemoveConfig("allow_pinning_ship"), RemoveConfig("r/^allow_pinning_[\\w]+_custom$"), RenameConfig("static_object_search_interval", "static_object_mapping_interval"), RenameConfig("need_to_equip_wishbone_for_underground_deposits", "need_to_equip_wishbone_for_underground_minerals"), RenameConfig("static_object_search_key", "static_object_mapping_key"), ReplaceValue("allow_pinning_animal", "All", "Boar, Piggy, Deer, Wolf, WolfCub, Lox, LoxCalf, Hen, Chicken, Hare, Bird, Fish"), ReplaceValue("allow_pinning_monster", "All", "Greyling, Neck, Ghost, Greydwarf, GreydwarfBrute, GreydwarfShaman, RancidRemains, Skeleton, Troll, Abomination, Blob, Draugr, DraugrElite, Leech, Oozer, Surtling, Wraith, Drake, Fenring, StoneGolem, Deathsquito, Fuling, FulingBerserker, FulingShaman, Growth, Serpent, Bat, FenringCultist, Ulv, DvergrRogue, DvergrMage, Tick, Seeker, SeekerBrood, Gjall, SeekerSoldier"), ReplaceValue("allow_pinning_flora", "All", "Dandelion, Mushroom, Raspberries, Blueberries, Carrot, CarrotSeeds, YellowMushroom, Thistle, Turnip, TurnipSeeds, Onion, OnionSeeds, Barley, Cloudberries, Flex, JotunPuffs, Magecap"), ReplaceValue("allow_pinning_mineral", "All", "CopperDeposit, TinDeposit, MudPile, ObsidianDeposit, SilverVein, PetrifiedBone, SoftTissue"), ReplaceValue("allow_pinning_spawner", "All", "GreydwarfNest, EvilBonePile, BodyPile"), ReplaceValue("allow_pinning_other", "All", "Vegvisir, Runestone, WildBeehive"), ReplaceValue("allow_pinning_dungeon", "All", "BurialChambers, TrollCave, SunkenCrypts, MountainCave, InfestedMine"), ReplaceValue("allow_pinning_spot", "All", "InfestedTree, FireHole, DrakeNest, GoblinCamp, TarPit, DvergrExcavation, DvergrGuardTower, DvergrHarbour, DvergrLighthouse, PetrifiedBone") } }, { "[automatic_processing]", new List { RemoveConfig("r/^([\\w_]+)_product_count_of_suppress_processing") } } }); } private static void MigrationFor145(List lines) { Migration(lines, new Dictionary> { { "[automatic_processing]", new List { ReplaceValue("r/^allow_processing_by", "All", "Craft, Refuel, Store") } } }); } private static void MigrationFor160(List lines) { Migration(lines, new Dictionary> { { "[automatic_mapping]", new List { AppendValues("allow_pinning_monster", new string[15] { "CharredMelee", "CharredArcher", "CharredMage", "CharredTwitcher", "CharredGrunt", "Morgen", "Volture", "BonemawSerpent", "FallenValkyrie", "Fader", "SkeletonFire", "FrostBlob", "Bear", "Vile", "LavaBlob" }), AppendValues("allow_pinning_animal", new string[2] { "Asksvin", "AsksvinHatchling" }), AppendValues("allow_pinning_flora", new string[4] { "Fiddlehead", "SmokePuff", "Vineberry", "VineberrySeeds" }), AppendValues("allow_pinning_mineral", new string[1] { "FlametalDeposit" }), AppendValues("allow_pinning_vehicle", new string[1] { "Drakkar" }), AppendValues("allow_pinning_spot", new string[3] { "CharredFortress", "LeviathanLava", "BogWitchCamp" }), AppendValues("allow_pinning_dungeon", new string[1] { "MorgenHole" }) } }, { "[automatic_mining]", new List { AppendValues("allow_mining_mineral", new string[1] { "FlametalDeposit" }) } }, { "[automatic_door]", new List { AppendValues("allow_automatic_door", new string[3] { "AshwoodDoor", "FlametalGate", "DvergrDoor" }) } }, { "[automatic_processing]", new List { AppendValues("allow_container", new string[1] { "PieceChestCharred" }) } } }); } private static void Migration(List lines, Dictionary> operations) { string category = ""; int begin = -1; int i; List value; for (i = 0; i < lines.Count; i++) { string text = lines[i]; if (text.StartsWith("#") || string.IsNullOrWhiteSpace(text) || !Regex.IsMatch(text, "^\\[[\\w\\d_]+\\]$")) { continue; } if (begin > 0 && operations.TryGetValue(category, out value)) { value.RemoveAll((Operation x) => x(category, lines, begin, i)); } category = text; begin = i; } if (operations.TryGetValue(category, out value)) { value.RemoveAll((Operation x) => x(category, lines, begin, i)); } foreach (KeyValuePair> item in operations.Where((KeyValuePair> pair) => pair.Value.Any())) { Automatics.Logger.Warning($"{item.Value.Count} migrations for {item.Key} were not performed."); } ConfigCache.Clear(); } private static Version ParseVersion(string line) { Match match = VersionPattern.Match(line); if (!match.Success) { Automatics.Logger.Error("Invalid version string: " + line); return new Version(0, 0, 0); } return new Version(int.Parse(match.Groups[1].Value), int.Parse(match.Groups[2].Value), int.Parse(match.Groups[3].Value)); } } internal static class ConfigurationManagerBridge { public static void Refresh() { ClearDrawerCache(); RebuildSettingList(); } private static void ClearDrawerCache() { try { AccessTools.Method("ConfigurationManager.SettingFieldDrawer:ClearCache", (Type[])null, (Type[])null)?.Invoke(null, Array.Empty()); } catch (Exception arg) { Automatics.Logger?.Debug($"Failed to clear ConfigurationManager cache\n{arg}"); } } private static void RebuildSettingList() { try { Type type = AccessTools.TypeByName("ConfigurationManager.ConfigurationManager"); if (!(type == null)) { object obj = AccessTools.Property(type, "Instance")?.GetValue(null, null); AccessTools.Method(type, "BuildSettingList", (Type[])null, (Type[])null)?.Invoke(obj, Array.Empty()); } } catch (Exception arg) { Automatics.Logger?.Debug($"Failed to rebuild ConfigurationManager setting list\n{arg}"); } } } internal static class Hooks { public static Action OnPlayerAwake { get; set; } public static Action OnPlayerUpdate { get; set; } public static Action OnPlayerFixedUpdate { get; set; } public static Action OnDedicatedServerFixedUpdate { get; set; } public static Action OnInitTerminal { get; set; } } [DisallowMultipleComponent] internal sealed class ContainerCache : InstanceCache { } [DisallowMultipleComponent] internal sealed class PickableCache : InstanceCache { } [HarmonyPatch] internal static class Patches { [HarmonyPostfix] [HarmonyPatch(typeof(Player), "Awake")] private static void Player_Awake_Postfix(Player __instance) { if (Objects.GetZNetView((Component)(object)__instance, out var zNetView)) { Hooks.OnPlayerAwake?.Invoke(__instance, zNetView); } } [HarmonyTranspiler] [HarmonyPatch(typeof(Player), "Update")] private static IEnumerable Player_Update_Transpiler(IEnumerable instructions, ILGenerator generator) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Expected O, but got Unknown //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Expected O, but got Unknown //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Expected O, but got Unknown //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Expected O, but got Unknown //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Expected O, but got Unknown //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Expected O, but got Unknown //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Expected O, but got Unknown //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Expected O, but got Unknown //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Expected O, but got Unknown Label label = default(Label); Label label2 = default(Label); return new CodeMatcher(instructions, generator).MatchEndForward((CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Call, (object)AccessTools.Method(typeof(Player), "UpdatePlacement", (Type[])null, (Type[])null), (string)null) }).Advance(1).CreateLabel(ref label) .Insert((CodeInstruction[])(object)new CodeInstruction[3] { new CodeInstruction(OpCodes.Ldarg_0, (object)null), new CodeInstruction(OpCodes.Ldloc_1, (object)null), new CodeInstruction(OpCodes.Callvirt, (object)AccessTools.Method(typeof(Action), "Invoke", (Type[])null, (Type[])null)) }) .CreateLabel(ref label2) .MatchStartBackwards((CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Ldarg_0, (object)null, (string)null) }) .Insert((CodeInstruction[])(object)new CodeInstruction[5] { new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(Hooks), "get_OnPlayerUpdate", (Type[])null, (Type[])null)), new CodeInstruction(OpCodes.Dup, (object)null), new CodeInstruction(OpCodes.Brtrue_S, (object)label2), new CodeInstruction(OpCodes.Pop, (object)null), new CodeInstruction(OpCodes.Br_S, (object)label) }) .InstructionEnumeration(); } [HarmonyTranspiler] [HarmonyPatch(typeof(Player), "FixedUpdate")] private static IEnumerable Player_FixedUpdate_Transpiler(IEnumerable instructions, ILGenerator generator) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Expected O, but got Unknown //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Expected O, but got Unknown //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Expected O, but got Unknown //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Expected O, but got Unknown //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Expected O, but got Unknown //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Expected O, but got Unknown //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Expected O, but got Unknown //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Expected O, but got Unknown //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Expected O, but got Unknown Label label = default(Label); Label label2 = default(Label); return new CodeMatcher(instructions, generator).MatchStartForward((CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Call, (object)AccessTools.Method(typeof(Player), "UpdateStealth", (Type[])null, (Type[])null), (string)null) }).Advance(1).CreateLabel(ref label) .Insert((CodeInstruction[])(object)new CodeInstruction[3] { new CodeInstruction(OpCodes.Ldarg_0, (object)null), new CodeInstruction(OpCodes.Ldloc_0, (object)null), new CodeInstruction(OpCodes.Callvirt, (object)AccessTools.Method(typeof(Action), "Invoke", (Type[])null, (Type[])null)) }) .CreateLabel(ref label2) .MatchStartBackwards((CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Ldarg_0, (object)null, (string)null) }) .Insert((CodeInstruction[])(object)new CodeInstruction[5] { new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(Hooks), "get_OnPlayerFixedUpdate", (Type[])null, (Type[])null)), new CodeInstruction(OpCodes.Dup, (object)null), new CodeInstruction(OpCodes.Brtrue_S, (object)label2), new CodeInstruction(OpCodes.Pop, (object)null), new CodeInstruction(OpCodes.Br_S, (object)label) }) .InstructionEnumeration(); } [HarmonyPrefix] [HarmonyPatch(typeof(Terminal), "InitTerminal")] private static void Terminal_InitTerminal_Prefix(out bool __state, bool ___m_terminalInitialized) { __state = ___m_terminalInitialized; } [HarmonyPostfix] [HarmonyPatch(typeof(Terminal), "InitTerminal")] private static void Terminal_InitTerminal_Postfix(bool __state) { if (!__state) { Hooks.OnInitTerminal?.Invoke(); } } [HarmonyPostfix] [HarmonyPatch(typeof(Container), "Awake")] private static void Container_Awake_Postfix(Container __instance, ZNetView ___m_nview) { if (Object.op_Implicit((Object)(object)___m_nview) && ___m_nview.GetZDO() != null) { ((Component)__instance).gameObject.AddComponent(); } } [HarmonyPostfix] [HarmonyPatch(typeof(Pickable), "Awake")] private static void Pickable_Awake_Postfix(Pickable __instance, ZNetView ___m_nview) { if (Object.op_Implicit((Object)(object)___m_nview) && ___m_nview.GetZDO() != null) { ((Component)__instance).gameObject.AddComponent(); } } } } namespace Automatics.Valheim { [Serializable] internal class ObjectMatcher { [NonSerialized] private bool _regex; [NonSerialized] private string _value; [NonSerialized] private Regex _pattern; public bool regex { get { return _regex; } set { _regex = value; OnUpdate(); } } public string value { get { return _value; } set { _value = value; OnUpdate(); } } public bool Matches(string name) { if (!regex || _pattern == null) { return string.Equals(name, _value, StringComparison.OrdinalIgnoreCase); } return _pattern.IsMatch(name); } private void OnUpdate() { _pattern = null; if (_regex && !string.IsNullOrEmpty(_value)) { _pattern = new Regex(_value); } } } [Serializable] internal class ObjectElement { public string identifier { get; set; } public string label { get; set; } public List matches { get; set; } public bool IsValid() { if (!string.IsNullOrEmpty(identifier) && !string.IsNullOrEmpty(label)) { return matches != null; } return false; } } [Serializable] internal class ObjectDataJson { public string type { get; set; } public int order { get; set; } public List values { get; set; } public bool IsValid() { if (!string.IsNullOrEmpty(type) && values != null) { return values.All((ObjectElement x) => x.IsValid()); } return false; } } internal static class ObjectElementList { private static bool _initialized; private static string EscapeForToml(string json) { StringBuilder stringBuilder = new StringBuilder(); bool flag = false; char[] array = json.ToCharArray(); foreach (char c in array) { switch (c) { case '\\': flag = true; stringBuilder.Append("$$"); continue; case '"': if (!flag) { stringBuilder.Append('\\'); } flag = false; break; default: flag = false; break; } stringBuilder.Append(c); } return stringBuilder.ToString(); } private static string UnescapeToml(string toml) { StringBuilder stringBuilder = new StringBuilder(); bool flag = false; char[] array = toml.ToCharArray(); foreach (char c in array) { switch (c) { case '\\': if (flag) { stringBuilder.Append('$'); } flag = false; continue; case '$': if (flag) { stringBuilder.Append('\\'); } flag = !flag; continue; } if (flag) { stringBuilder.Append('$'); } flag = false; stringBuilder.Append(c); } return stringBuilder.ToString(); } private static Action GetCustomDrawer() { string identifierInput = ""; string labelInput = ""; string valueInput = ""; return delegate(ConfigEntryBase entry) { //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Expected O, but got Unknown //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Expected O, but got Unknown //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Expected O, but got Unknown //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Expected O, but got Unknown //IL_0375: Unknown result type (might be due to invalid IL or missing references) //IL_037f: Expected O, but got Unknown //IL_037a: Unknown result type (might be due to invalid IL or missing references) //IL_0394: Unknown result type (might be due to invalid IL or missing references) //IL_039e: Expected O, but got Unknown //IL_0399: Unknown result type (might be due to invalid IL or missing references) //IL_03fc: Unknown result type (might be due to invalid IL or missing references) //IL_0415: Expected O, but got Unknown int num = Mathf.Min(Screen.width, 650); int num2 = num - Mathf.RoundToInt((float)num / 2.5f) - 115; string text = Automatics.L10N.Translate("mod_utils_config_button_add"); string text2 = Automatics.L10N.Translate("mod_utils_config_button_remove"); string text3 = Automatics.L10N.Translate("@config_object_element_identifier"); string text4 = Automatics.L10N.Translate("@config_object_element_label"); string text5 = Automatics.L10N.Translate("@config_object_element_value"); float num3 = Mathf.Max(new float[3] { GUI.skin.label.CalcSize(new GUIContent(text3)).x, GUI.skin.label.CalcSize(new GUIContent(text4)).x, GUI.skin.label.CalcSize(new GUIContent(text5)).x }); List list = new List((List)entry.BoxedValue); GUILayout.BeginVertical((GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.MaxWidth((float)num2) }); GUILayout.BeginHorizontal(Array.Empty()); GUILayout.Label(new GUIContent(text3, ""), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(num3) }); identifierInput = GUILayout.TextField(string.Concat(identifierInput.Where((char x) => !char.IsWhiteSpace(x))), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) }); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(Array.Empty()); GUILayout.Label(text4, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(num3) }); labelInput = GUILayout.TextField(labelInput, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) }); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(Array.Empty()); GUILayout.Label(text5, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(num3) }); valueInput = GUILayout.TextField(valueInput, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) }); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(Array.Empty()); if (GUILayout.Button(text, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) }) && !string.IsNullOrEmpty(identifierInput) && !string.IsNullOrEmpty(labelInput) && !string.IsNullOrEmpty(valueInput)) { bool flag = valueInput.StartsWith("r/"); valueInput = (flag ? valueInput.Substring(2) : valueInput); list.Add(new ObjectElement { identifier = identifierInput, label = labelInput, matches = new List { new ObjectMatcher { regex = flag, value = valueInput } } }); entry.BoxedValue = list; identifierInput = ""; labelInput = ""; valueInput = ""; } GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(Array.Empty()); double num4 = 0.0; foreach (ObjectElement item in list.ToList()) { string identifier = item.identifier; string label = item.label; string text6 = Automatics.L10N.TranslateInternalName(label); string value = item.matches[0].value; int num5 = Mathf.FloorToInt(GUI.skin.label.CalcSize(new GUIContent(text6)).x) + Mathf.FloorToInt(GUI.skin.button.CalcSize(new GUIContent(text2)).x); num4 += (double)num5; if (num4 > (double)num2) { GUILayout.EndHorizontal(); num4 = num5; GUILayout.BeginHorizontal(Array.Empty()); } string text7 = Automatics.L10N.LocalizeTextOnly("@config_object_element_preview", text6, label, identifier, value); GUILayout.Label(new GUIContent(text6, text7), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(false) }); if (GUILayout.Button(text2, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(false) }) && list.Remove(item)) { entry.BoxedValue = list; } } GUILayout.EndHorizontal(); GUILayout.EndVertical(); GUILayout.FlexibleSpace(); }; } public static void Initialize() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Expected O, but got Unknown if (!_initialized) { _initialized = true; TomlTypeConverter.AddConverter(typeof(List), new TypeConverter { ConvertToObject = (string str, Type type) => (!string.IsNullOrEmpty(str)) ? Json.Parse>(UnescapeToml(str.Trim('"'))) : new List(), ConvertToString = delegate(object obj, Type type) { List list = (List)obj; return (!list.Any()) ? "" : ("\"" + EscapeForToml(Json.ToString(list)) + "\""); } }); ConfigurationCustomDrawer.Register((Type type, AcceptableValueBase value) => type == typeof(List), GetCustomDrawer); } } } internal class ValheimObject { private static readonly List JsonCache; public static readonly ValheimObject Animal; public static readonly ValheimObject Dungeon; public static readonly ValheimObject Flora; public static readonly ValheimObject Mineral; public static readonly ValheimObject Monster; public static readonly ValheimObject Spawner; public static readonly ValheimObject Spot; private readonly string _type; private readonly Dictionary _elements; private readonly Dictionary _customElements; private readonly List _allElements; public static event Action RegistryChanged; static ValheimObject() { JsonCache = new List(); Animal = new ValheimObject("animal"); Dungeon = new ValheimObject("dungeon"); Flora = new ValheimObject("flora"); Mineral = new ValheimObject("mineral"); Monster = new ValheimObject("monster"); Spawner = new ValheimObject("spawner"); Spot = new ValheimObject("spot"); ObjectElementList.Initialize(); } public ValheimObject(string type) { _type = type; _elements = new Dictionary(); _customElements = new Dictionary(); _allElements = new List(); if (JsonCache.Any()) { Register(JsonCache); } } private static void Initialize(string directory) { if (!Directory.Exists(directory)) { Automatics.Logger.Debug("Directory does not exist: " + directory); return; } JsonCache.AddRange(from x in Directory.EnumerateFiles(directory, "*.json", SearchOption.AllDirectories).Select(delegate(string x) { try { return Json.Parse(File.ReadAllText(x)); } catch (Exception arg) { Automatics.Logger.Error($"Failed to read Json file\n{arg}"); return new ObjectDataJson(); } }) where x.IsValid() select x); } public static void Initialize(IEnumerable directories) { foreach (string directory in directories) { Initialize(directory); } Animal.Register(JsonCache); Dungeon.Register(JsonCache); Flora.Register(JsonCache); Mineral.Register(JsonCache); Monster.Register(JsonCache); Spawner.Register(JsonCache); Spot.Register(JsonCache); } public static void PostInitialize() { JsonCache.Clear(); } private void UpdateElements() { _allElements.Clear(); _allElements.AddRange(_elements.Values); _allElements.AddRange(_customElements.Values); } private void Register(IEnumerable jsons) { foreach (ObjectElement item in (from x in jsons where x.type.ToLower() == _type orderby x.order select x).SelectMany((ObjectDataJson x) => x.values)) { _elements[item.identifier.ToLower()] = new ObjectElement { identifier = item.identifier, label = item.label, matches = new List(item.matches) }; } UpdateElements(); } public void RegisterCustom(IEnumerable elements) { _customElements.Clear(); foreach (ObjectElement element in elements) { _customElements[element.identifier.ToLower()] = new ObjectElement { identifier = element.identifier, label = element.label, matches = new List(element.matches) }; } UpdateElements(); ValheimObject.RegistryChanged?.Invoke(this); } public IEnumerable GetElements() { return new List(_elements.Values); } public IEnumerable GetCustomElements() { return new List(_customElements.Values); } public IEnumerable GetAllElements() { return _allElements.ToList(); } public bool GetIdentify(string name, out string identifier) { ObjectElement objectElement = _allElements.FirstOrDefault((ObjectElement x) => x.matches.Any((ObjectMatcher y) => y.Matches(name))); if (objectElement == null || !objectElement.IsValid()) { identifier = ""; return false; } identifier = objectElement.identifier; return true; } public bool GetName(string identifier, out string name) { string key = identifier.ToLower(); if (!_elements.TryGetValue(key, out var value) && !_customElements.TryGetValue(key, out value)) { name = ""; return false; } name = value.label; return true; } public bool IsDefined(string nameOrIdentify) { if (!GetIdentify(nameOrIdentify, out var identifier)) { return GetName(nameOrIdentify, out identifier); } return true; } } } namespace Automatics.ConsoleCommands { internal abstract class Command { private static readonly Dictionary Commands; private static readonly List EmptyList; private readonly Lazy _optionsLazy; protected readonly string command; protected List extraOptions; private bool _showHelp; protected OptionSet options => _optionsLazy.Value; protected bool HaveExtraOption { get; set; } protected bool HaveExtraDescription { get; set; } static Command() { Commands = new Dictionary(); EmptyList = new List(); } protected Command(string command) { this.command = command.ToLower(); _optionsLazy = new Lazy(delegate { OptionSet optionSet = CreateOptionSet(); optionSet.Add("h|help", Automatics.L10N.Translate("@command_common_help_description"), delegate(string v) { _showHelp = v != null; }); return optionSet; }); extraOptions = new List(); } private static IEnumerable ParseArgs(string line) { List list = new List(); StringBuilder stringBuilder = new StringBuilder(); bool flag = false; bool flag2 = false; foreach (char c in line) { switch (c) { case '\\': if (!flag2) { flag2 = true; continue; } break; case '"': if (!flag2) { flag = !flag; continue; } break; case ' ': if (!flag) { list.Add(stringBuilder.ToString()); stringBuilder.Clear(); flag2 = false; continue; } break; } stringBuilder.Append(c); flag2 = false; } if (stringBuilder.Length > 0) { list.Add(stringBuilder.ToString()); } return list.Skip(1).ToList(); } protected static IEnumerable<(string Command, Command Instance)> GetAllCommands() { return Commands.Select((KeyValuePair x) => (x.Key, x.Value)); } [Conditional("DEBUG")] private void DebugLog() { Automatics.Logger.Debug("[COMMAND]: ### " + command); string[] array = Help().Split(new char[1] { '\n' }, StringSplitOptions.None); foreach (string text in array) { Automatics.Logger.Debug("[COMMAND]: " + text.Trim()); } } protected abstract void CommandAction(ConsoleEventArgs args); protected virtual OptionSet CreateOptionSet() { return new OptionSet(); } protected virtual List GetSuggestions() { return EmptyList; } protected virtual void ResetOptions() { _showHelp = false; } protected bool ParseArgs(ConsoleEventArgs args) { ResetOptions(); try { extraOptions = options.Parse(ParseArgs(args.FullLine)); } catch (OptionException ex) { args.Context.AddString(command + ":"); args.Context.AddString(ex.Message); args.Context.AddString(Automatics.L10N.LocalizeTextOnly("@command_common_option_parse_error", command)); return false; } if (!_showHelp) { return true; } args.Context.AddString(Help()); return false; } protected string Usage() { return Automatics.L10N.Translate("@command_" + command + "_usage"); } protected string Description() { return Automatics.L10N.Translate("@command_" + command + "_description"); } protected string ExtraOption() { return Automatics.L10N.Translate("@command_" + command + "_extra_option"); } protected string ExtraDescription() { return Automatics.L10N.Translate("@command_" + command + "_extra_description"); } protected string Help() { StringWriter stringWriter = new StringWriter(); stringWriter.WriteLine(Usage()); stringWriter.WriteLine(Description()); if (HaveExtraOption) { stringWriter.WriteLine(); stringWriter.WriteLine(ExtraOption()); } stringWriter.WriteLine(); stringWriter.WriteLine(Automatics.L10N.Translate("@command_common_help_options_label")); options.WriteOptionDescriptions(stringWriter); if (HaveExtraDescription) { stringWriter.WriteLine(); stringWriter.WriteLine(ExtraDescription()); } return stringWriter.ToString(); } public string Print(bool verbose) { if (verbose) { return Help(); } return "\"" + command + "\" " + Description(); } public void Register(bool isCheat = false, bool isNetwork = false, bool onlyServer = false, bool isSecret = false, bool allowInDevBuild = false) { //IL_0025: 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_0046: Expected O, but got Unknown //IL_0046: Expected O, but got Unknown //IL_0041: Unknown result type (might be due to invalid IL or missing references) Commands[command] = this; new ConsoleCommand(command, Description(), new ConsoleEvent(CommandAction), isCheat, isNetwork, onlyServer, isSecret, allowInDevBuild, new ConsoleOptionsFetcher(GetSuggestions), false, false, false); } } internal class PrintNames : Command { public PrintNames() : base("printnames") { base.HaveExtraOption = true; base.HaveExtraDescription = true; } protected override void CommandAction(ConsoleEventArgs args) { if (!ParseArgs(args)) { return; } Automatics.Logger.Message(() => "Command exec: " + args.FullLine); List<(bool Regex, string Value)> filters = extraOptions.Select((string arg) => (!arg.StartsWith("r/", StringComparison.OrdinalIgnoreCase)) ? (false, arg) : (true, arg.Substring(2))).ToList(); foreach (var item3 in from <>h__TransparentIdentifier0 in GetAllTranslations().Select(delegate(KeyValuePair translation) { KeyValuePair keyValuePair = translation; string key; if (!keyValuePair.Key.StartsWith("automatics_")) { keyValuePair = translation; key = "$" + keyValuePair.Key; } else { keyValuePair = translation; key = "@" + keyValuePair.Key.Substring(11); } return new { translation, key }; }) let value = translation.Value where filters.All(delegate((bool Regex, string Value) filter) { if (!filter.Regex) { if (key.IndexOf(filter.Value, StringComparison.OrdinalIgnoreCase) < 0) { return value.IndexOf(filter.Value, StringComparison.OrdinalIgnoreCase) >= 0; } return true; } return Regex.IsMatch(key, filter.Value) || Regex.IsMatch(value, filter.Value); }) select (key, value)) { string item = item3.Item1; string item2 = item3.Item2; string text = Automatics.L10N.LocalizeTextOnly("@command_printnames_result_format", item, item2); args.Context.AddString(text); Automatics.Logger.Message(() => " " + text); } args.Context.AddString(""); static Dictionary GetAllTranslations() { return Reflections.GetField>(Localization.instance, "m_translations"); } } } internal class PrintObjects : Command { private static readonly Collider[] ColliderBuffer; private int _radius; private int _number; private string _include; private string _exclude; static PrintObjects() { ColliderBuffer = (Collider[])(object)new Collider[4096]; } public PrintObjects() : base("printobjects") { base.HaveExtraOption = true; base.HaveExtraDescription = true; } private static (bool IsValid, bool IsRegex, string Value) CreateFilter(string arg) { if (string.IsNullOrEmpty(arg)) { return (false, false, ""); } if (!arg.StartsWith("r/", StringComparison.OrdinalIgnoreCase)) { return (true, false, arg); } return (true, true, arg.Substring(2)); } private static bool MatchesFilter(string name, (bool IsValid, bool IsRegex, string Value) filter) { bool flag = (filter.IsRegex ? Regex.IsMatch(name, filter.Value) : (name.IndexOf(filter.Value, StringComparison.OrdinalIgnoreCase) >= 0)); if (flag) { return true; } string text = Automatics.L10N.TranslateInternalName(name); if (name != text) { flag = (filter.IsRegex ? Regex.IsMatch(text, filter.Value) : (text.IndexOf(filter.Value, StringComparison.OrdinalIgnoreCase) >= 0)); } return flag; } private static void PrintLine(ConsoleEventArgs args, string message) { args.Context.AddString(message); string[] array = message.Split(new char[1] { '\n' }, StringSplitOptions.None); foreach (string text in array) { Automatics.Logger.Message(text.Trim()); } } protected override OptionSet CreateOptionSet() { return new OptionSet { { "r|radius=", Automatics.L10N.Translate("@command_printobjects_option_radius_description"), delegate(int x) { _radius = x; } }, { "n|number=", Automatics.L10N.Translate("@command_printobjects_option_number_description"), delegate(int x) { _number = x; } }, { "i|include=", Automatics.L10N.Translate("@command_printobjects_option_include_description"), delegate(string x) { _include = x; } }, { "e|exclude=", Automatics.L10N.Translate("@command_printobjects_option_exclude_description"), delegate(string x) { _exclude = x; } } }; } protected override List GetSuggestions() { return new List { "animal", "dungeon", "door", "container", "flora", "mineral", "monster", "other", "spawner", "spot", "vehicle" }; } protected override void ResetOptions() { base.ResetOptions(); _radius = 32; _number = 4; _include = ""; _exclude = ""; } protected override void CommandAction(ConsoleEventArgs args) { if (!ParseArgs(args)) { return; } Automatics.Logger.Message(() => "Command exec: " + args.FullLine); string text = (extraOptions.FirstOrDefault() ?? "").ToLower(); if (text == null) { return; } switch (text.Length) { case 7: switch (text[1]) { case 'o': if (text == "monster") { PrintMonster(args); } break; case 'i': if (text == "mineral") { PrintMineral(args); } break; case 'p': if (text == "spawner") { PrintSpawner(args); } break; case 'e': if (text == "vehicle") { PrintVehicle(args); } break; case 'u': if (text == "dungeon") { PrintDungeon(args); } break; } break; case 5: switch (text[0]) { case 'f': if (text == "flora") { PrintFlora(args); } break; case 'o': if (text == "other") { PrintOther(args); } break; } break; case 4: switch (text[0]) { case 's': if (text == "spot") { PrintSpot(args); } break; case 'd': if (text == "door") { PrintDoor(args); } break; } break; case 6: if (text == "animal") { PrintAnimal(args); } break; case 9: if (text == "container") { PrintContainer(args); } break; case 8: break; } } private void PrintObject(ConsoleEventArgs args, string type, ValheimObject vObject, IEnumerable objects, Predicate predicate = null) { //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0235: Unknown result type (might be due to invalid IL or missing references) //IL_01ed: Unknown result type (might be due to invalid IL or missing references) if (predicate == null) { predicate = (MonoBehaviour behaviour) => true; } string text = Automatics.L10N.Translate("@command_printobjects_message_type_" + type); (bool, bool, string) filter = CreateFilter(_include); (bool, bool, string) filter2 = CreateFilter(_exclude); HashSet hashSet = new HashSet(); int num = 0; Vector3 origin = ((Component)Player.m_localPlayer).transform.position; foreach (var item3 in from x in objects let distance = Vector3.Distance(origin, ((Component)x).transform.position) where distance < (float)_radius && predicate(x) orderby distance select (x, distance.ToString("F1"))) { MonoBehaviour item = item3.Item1; string item2 = item3.Item2; string name = Objects.GetName((Component)(object)item); if (hashSet.Add(name) && (!filter.Item1 || MatchesFilter(name, filter)) && (!filter2.Item1 || !MatchesFilter(name, filter2)) && ++num <= _number) { string identifier; bool identify = vObject.GetIdentify(name, out identifier); if (!identify) { identifier = PrefabNameToIdentifier(Objects.GetPrefabName(((Component)item).gameObject)); } string text2 = Automatics.L10N.Translate(name); string message = (identify ? Automatics.L10N.LocalizeTextOnly("@command_printobjects_message_result_defined", text2, name, text, ((Component)item).transform.position, item2, identifier) : Automatics.L10N.LocalizeTextOnly("@command_printobjects_message_result", text2, name, ((Component)item).transform.position, item2, identifier, name)); PrintLine(args, message); args.Context.AddString(""); } } if (num > _number) { PrintLine(args, Automatics.L10N.Localize("@command_printobjects_message_result_more", num - _number, text)); } else if (num == 0) { PrintLine(args, Automatics.L10N.Localize("@command_printobjects_message_result_empty", text)); } } private void PrintAnimal(ConsoleEventArgs args) { List list = new List(); list.AddRange((IEnumerable)(from x in Character.GetAllCharacters() where Object.op_Implicit((Object)(object)((Component)x).GetComponent()) || Object.op_Implicit((Object)(object)((Component)x).GetComponent()) select x)); list.AddRange((IEnumerable)InstanceCache.GetAllInstance()); list.AddRange((IEnumerable)InstanceCache.GetAllInstance()); PrintObject(args, "animal", ValheimObject.Animal, list, (MonoBehaviour x) => true); } private void PrintMonster(ConsoleEventArgs args) { PrintObject(args, "monster", ValheimObject.Monster, (IEnumerable)Character.GetAllCharacters(), (MonoBehaviour x) => Object.op_Implicit((Object)(object)((Component)x).GetComponent()) && !Object.op_Implicit((Object)(object)((Component)x).GetComponent())); } private void PrintFlora(ConsoleEventArgs args) { PrintObject(args, "flora", ValheimObject.Flora, (IEnumerable)InstanceCache.GetAllInstance(), (MonoBehaviour x) => true); } private void PrintMineral(ConsoleEventArgs args) { PrintObject(args, "mineral", ValheimObject.Mineral, GetObjects(delegate(MonoBehaviour x) { MineRock component = ((Component)x).GetComponent(); if (Object.op_Implicit((Object)(object)component)) { return (MonoBehaviour)(object)component; } MineRock5 component2 = ((Component)x).GetComponent(); return (MonoBehaviour)(Object.op_Implicit((Object)(object)component2) ? ((object)component2) : ((object)((Component)x).GetComponent())); })); } private void PrintSpawner(ConsoleEventArgs args) { PrintObject(args, "spawner", ValheimObject.Spawner, GetObjects((MonoBehaviour x) => (MonoBehaviour)(object)((Component)x).GetComponent())); } private void PrintVehicle(ConsoleEventArgs args) { List list = new List(); list.AddRange((IEnumerable)InstanceCache.GetAllInstance()); list.AddRange((IEnumerable)(Reflections.GetStaticField>("m_instances") ?? new List(0))); PrintObject(args, "vehicle", MappingObject.Vehicle, list, (MonoBehaviour x) => true); } private void PrintOther(ConsoleEventArgs args) { PrintObject(args, "other", MappingObject.Other, GetObjects(delegate(MonoBehaviour x) { IDestructible component = ((Component)x).GetComponent(); MonoBehaviour val = (MonoBehaviour)(object)((component is MonoBehaviour) ? component : null); if (val != null) { return val; } Interactable component2 = ((Component)x).GetComponent(); MonoBehaviour val2 = (MonoBehaviour)(object)((component2 is MonoBehaviour) ? component2 : null); if (val2 != null) { return val2; } Hoverable component3 = ((Component)x).GetComponent(); MonoBehaviour val3 = (MonoBehaviour)(object)((component3 is MonoBehaviour) ? component3 : null); return (val3 != null) ? val3 : null; })); } private void PrintDungeon(ConsoleEventArgs args) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: 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_0172: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_01f8: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: Unknown result type (might be due to invalid IL or missing references) string text = Automatics.L10N.Translate("@command_printobjects_message_type_dungeon"); int num = 0; HashSet hashSet = new HashSet(); Vector3 origin = ((Component)Player.m_localPlayer).transform.position; foreach (LocationInstance item2 in ZoneSystem.instance.m_locationInstances.Values.Where((LocationInstance x) => Vector3.Distance(origin, x.m_position) < (float)_radius)) { string prefabName = item2.m_location.m_prefabName; string text2 = prefabName; if (!hashSet.Add(text2)) { continue; } string identifier; bool identify = ValheimObject.Dungeon.GetIdentify(text2, out identifier); if (!identify) { identifier = PrefabNameToIdentifier(text2); } bool flag = false; using (IEnumerator<(Collider, Teleport, float)> enumerator2 = (from x in Objects.GetInsideSphere(item2.m_position, item2.m_location.m_exteriorRadius, (Collider x) => ((Component)x).GetComponent(), ColliderBuffer, LayerMask.GetMask(new string[1] { "character_trigger" })) orderby x.distance select x).GetEnumerator()) { if (enumerator2.MoveNext()) { (Collider, Teleport, float) current2 = enumerator2.Current; Collider item = current2.Item1; text2 = current2.Item2.m_enterText; string text3 = Automatics.L10N.Translate(text2); Bounds bounds = item.bounds; Vector3 center = ((Bounds)(ref bounds)).center; string text4 = Vector3.Distance(origin, center).ToString("F1"); string message = (identify ? Automatics.L10N.LocalizeTextOnly("@command_printobjects_message_result_defined", text3, text2, text, center, text4, identifier) : Automatics.L10N.LocalizeTextOnly("@command_printobjects_message_result", text3, text2, center, text4, identifier, prefabName)); PrintLine(args, message); flag = true; num++; } } if (flag) { if (num >= _number) { break; } args.Context.AddString(""); } } if (num > _number) { PrintLine(args, Automatics.L10N.Localize("@command_printobjects_message_result_more", num - _number, text)); } else if (num == 0) { PrintLine(args, Automatics.L10N.Localize("@command_printobjects_message_result_empty", text)); } } private void PrintSpot(ConsoleEventArgs args) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0121: 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_0125: Unknown result type (might be due to invalid IL or missing references) //IL_0267: Unknown result type (might be due to invalid IL or missing references) //IL_0229: Unknown result type (might be due to invalid IL or missing references) string text = Automatics.L10N.Translate("@command_printobjects_message_type_spot"); int num = 0; HashSet hashSet = new HashSet(); Vector3 origin = ((Component)Player.m_localPlayer).transform.position; foreach (var item3 in from x in ZoneSystem.instance.m_locationInstances.Values let distance = Vector3.Distance(origin, x.m_position) where distance < (float)_radius select (x, distance)) { LocationInstance item = item3.Item1; float item2 = item3.Item2; string prefabName = item.m_location.m_prefabName; string name = prefabName; if (!hashSet.Add(name)) { continue; } string identifier; bool identify = ValheimObject.Spot.GetIdentify(name, out identifier); if (!identify) { identifier = PrefabNameToIdentifier(name); } bool flag = false; Vector3 position = item.m_position; using (IEnumerator<(Collider, Teleport, float)> enumerator2 = (from x in Objects.GetInsideSphere(position, item.m_location.m_exteriorRadius, (Collider x) => ((Component)x).GetComponent(), ColliderBuffer, LayerMask.GetMask(new string[1] { "character_trigger" })) orderby x.distance select x).GetEnumerator()) { if (enumerator2.MoveNext()) { _ = enumerator2.Current; flag = true; } } if (!flag) { if (identify) { ValheimObject.Spot.GetName(identifier, out name); } else { name = "@location_" + name.ToLower(); } string text2 = Automatics.L10N.Translate(name); string text3 = item2.ToString("F1"); string message = (identify ? Automatics.L10N.LocalizeTextOnly("@command_printobjects_message_result_defined", text2, name, text, position, text3, identifier) : Automatics.L10N.LocalizeTextOnly("@command_printobjects_message_result", text2, name, position, text3, identifier, prefabName)); PrintLine(args, message); if (++num >= _number) { break; } args.Context.AddString(""); } } if (num > _number) { PrintLine(args, Automatics.L10N.Localize("@command_printobjects_message_result_more", num - _number, text)); } else if (num == 0) { PrintLine(args, Automatics.L10N.Localize("@command_printobjects_message_result_empty", text)); } } private void PrintDoor(ConsoleEventArgs args) { PrintObject(args, "door", global::Automatics.AutomaticDoor.Globals.Door, GetObjects((MonoBehaviour x) => (MonoBehaviour)(object)((Component)x).GetComponent())); } private void PrintContainer(ConsoleEventArgs args) { PrintObject(args, "container", global::Automatics.AutomaticProcessing.Globals.Container, (IEnumerable)InstanceCache.GetAllInstance()); } private IEnumerable GetObjects(Func converter = null) { //IL_0039: 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) if (converter == null) { converter = (MonoBehaviour x) => x; } List list = new List(4096); int num = Physics.OverlapBoxNonAlloc(((Component)Player.m_localPlayer).transform.position, new Vector3((float)_radius, (float)_radius, (float)_radius), ColliderBuffer); for (int i = 0; i < num; i++) { MonoBehaviour componentInParent = ((Component)ColliderBuffer[i]).GetComponentInParent(); if (Object.op_Implicit((Object)(object)componentInParent)) { componentInParent = converter(componentInParent); if (Object.op_Implicit((Object)(object)componentInParent)) { list.Add(componentInParent); } } } return list; } private static string PrefabNameToIdentifier(string prefabName) { StringBuilder stringBuilder = new StringBuilder(); bool flag = true; char[] array = prefabName.ToCharArray(); foreach (char c in array) { if (c == '_') { flag = true; } else if (char.IsLetter(c) || char.IsDigit(c)) { stringBuilder.Append(flag ? char.ToUpper(c) : c); flag = false; } } return stringBuilder.ToString(); } } internal class RemoveMapPins : Command { private int _radius; private string _include; private string _exclude; private bool _dryRun; private bool _dangerousMode; public RemoveMapPins() : base("removemappins") { } protected override OptionSet CreateOptionSet() { return new OptionSet { { "r|radius=", Automatics.L10N.Translate("@command_removemappins_option_radius_description"), delegate(int x) { _radius = x; } }, { "i|include=", Automatics.L10N.Translate("@command_removemappins_option_include_description"), delegate(string x) { _include = x; } }, { "e|exclude=", Automatics.L10N.Translate("@command_removemappins_option_exclude_description"), delegate(string x) { _exclude = x; } }, { "n|dry-run", Automatics.L10N.Translate("@command_removemappins_option_dry_run_description"), delegate(string x) { _dryRun = x != null; } }, { "d|dangerous-mode", Automatics.L10N.Translate("@command_removemappins_option_dangerous_mode_description"), delegate(string x) { _dangerousMode = x != null; } } }; } protected override void ResetOptions() { base.ResetOptions(); _radius = 0; _include = ""; _exclude = ""; _dryRun = false; _dangerousMode = false; } protected override void CommandAction(ConsoleEventArgs args) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)Player.m_localPlayer) || !ParseArgs(args)) { return; } Vector3 origin = ((Component)Player.m_localPlayer).transform.position; List list = new List(); foreach (PinData item in Reflections.GetField>(Minimap.instance, "m_pins")) { if (_radius <= 0 || !(Utils.DistanceXZ(origin, item.m_pos) > (float)_radius)) { string text = Automatics.L10N.Translate(item.m_name); if ((string.IsNullOrEmpty(_include) || text.IndexOf(_include, StringComparison.OrdinalIgnoreCase) != -1) && (string.IsNullOrEmpty(_exclude) || text.IndexOf(_exclude, StringComparison.OrdinalIgnoreCase) < 0)) { list.Add(item); } } } if (!_dangerousMode) { HashSet positions = new HashSet(); list = list.Where((PinData pin) => !positions.Add(pin.m_pos)).ToList(); } string msg = Automatics.L10N.Localize("@command_removemappins_message_remove_pins", list.Count); args.Context.AddString(msg); Automatics.Logger.Message(msg); list.ForEach(delegate(PinData pin) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) msg = Automatics.L10N.Localize("@command_removemappins_message_pin_data", pin.m_name, pin.m_pos, Utils.DistanceXZ(origin, pin.m_pos)); args.Context.AddString(msg); Automatics.Logger.Message(msg); if (!_dryRun) { Minimap.instance.RemovePin(pin); } }); if (!_dangerousMode) { args.Context.AddString(Automatics.L10N.Translate("@command_removemappins_message_safe_mode")); } } } internal class ShowCommands : Command { private string _include; private string _exclude; private bool _verbose; public ShowCommands() : base("automatics") { } protected override OptionSet CreateOptionSet() { return new OptionSet { { "i|include=", Automatics.L10N.Translate("@command_automatics_option_include_description"), delegate(string x) { _include = x; } }, { "e|exclude=", Automatics.L10N.Translate("@command_automatics_option_exclude_description"), delegate(string x) { _exclude = x; } }, { "v|verbose", Automatics.L10N.Translate("@command_automatics_option_verbose_description"), delegate(string x) { _verbose = x != null; } } }; } protected override void ResetOptions() { base.ResetOptions(); _include = ""; _exclude = ""; _verbose = false; } protected override void CommandAction(ConsoleEventArgs args) { if (!ParseArgs(args)) { return; } foreach (var (text, command) in Command.GetAllCommands()) { if ((string.IsNullOrEmpty(_include) || text.IndexOf(_include, StringComparison.OrdinalIgnoreCase) != -1) && (string.IsNullOrEmpty(_exclude) || text.IndexOf(_exclude, StringComparison.OrdinalIgnoreCase) < 0)) { args.Context.AddString(command.Print(_verbose)); } } } } } namespace Automatics.AutomaticRepair { internal static class Config { private const string Section = "automatic_repair"; private static ConfigEntry _module; private static ConfigEntry _enableAutomaticRepair; private static ConfigEntry _craftingStationSearchRange; private static ConfigEntry _repairItemsWhenAccessingTheCraftingStation; private static ConfigEntry _itemRepairMessage; private static ConfigEntry _pieceSearchRange; private static ConfigEntry _pieceRepairMessage; public static bool ModuleDisabled => _module.Value == AutomaticsModule.Disabled; public static bool EnableAutomaticRepair => _enableAutomaticRepair.Value; public static int CraftingStationSearchRange => _craftingStationSearchRange.Value; public static bool RepairItemsWhenAccessingTheCraftingStation => _repairItemsWhenAccessingTheCraftingStation.Value; public static Message ItemRepairMessage => _itemRepairMessage.Value; public static int PieceSearchRange => _pieceSearchRange.Value; public static Message PieceRepairMessage => _pieceRepairMessage.Value; public static void Initialize() { Configuration instance = global::Automatics.Config.Instance; instance.ChangeSection("automatic_repair"); _module = instance.Bind("module", AutomaticsModule.Enabled, null, delegate(ConfigurationManagerAttributes x) { x.DispName = Automatics.L10N.Translate("@config_common_disable_module_name"); x.Description = Automatics.L10N.Translate("@config_common_disable_module_description"); }); if (_module.Value != AutomaticsModule.Disabled) { _enableAutomaticRepair = instance.Bind("enable_automatic_repair", defaultValue: true); _craftingStationSearchRange = instance.Bind("crafting_station_search_range", 16, (0, 64)); _repairItemsWhenAccessingTheCraftingStation = instance.Bind("repair_items_when_accessing_the_crafting_station", defaultValue: false); _itemRepairMessage = instance.Bind("item_repair_message", Message.None); _pieceSearchRange = instance.Bind("piece_search_range", 16, (0, 64)); _pieceRepairMessage = instance.Bind("piece_repair_message", Message.None); } } } internal static class ItemRepair { private static readonly List WornItemsBuffer; static ItemRepair() { WornItemsBuffer = new List(); } private static void ShowRepairMessage(Player player, int repairCount) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) if (repairCount != 0) { Automatics.Logger.Debug(() => $"Repaired {repairCount} items"); if (Config.ItemRepairMessage != 0) { MessageType val = (MessageType)((Config.ItemRepairMessage != Message.Center) ? 1 : 2); ((Character)player).Message(val, Automatics.L10N.Localize("@message_automatic_repair_repaired_the_items", repairCount), 0, (Sprite)null); } } } private static IEnumerable GetAllCraftingStations() { IEnumerable staticField = Reflections.GetStaticField>("m_allStations"); return staticField ?? Enumerable.Empty(); } private static int RepairAll(Player player, CraftingStation station) { WornItemsBuffer.Clear(); ((Humanoid)player).GetInventory().GetWornItems(WornItemsBuffer); return WornItemsBuffer.Count((ItemData x) => RepairOne(player, station, x)); } private static bool RepairOne(Player player, CraftingStation station, ItemData item) { if (!CanRepair(player, station, item)) { return false; } item.m_durability = item.GetMaxDurability(); Automatics.Logger.Debug(() => "Repair item: [" + item.m_shared.m_name + "(" + Automatics.L10N.Translate(item.m_shared.m_name) + ")]"); return true; } private static bool CanRepair(Player player, CraftingStation station, ItemData item) { if (!item.m_shared.m_canBeReparied) { return false; } if (player.NoCostCheat()) { return true; } Recipe recipe = ObjectDB.instance.GetRecipe(item); if ((Object)(object)recipe != (Object)null && ((Object)(object)recipe.m_craftingStation != (Object)null || (Object)(object)recipe.m_repairStation != (Object)null) && (((Object)(object)recipe.m_craftingStation != (Object)null && recipe.m_craftingStation.m_name == station.m_name) || ((Object)(object)recipe.m_repairStation != (Object)null && recipe.m_repairStation.m_name == station.m_name))) { return station.GetLevel(true) >= recipe.m_minStationLevel; } return false; } public static void CraftingStationInteractHook(Player player, CraftingStation station) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) if (Config.EnableAutomaticRepair && Config.RepairItemsWhenAccessingTheCraftingStation) { int num = RepairAll(player, station); if (num != 0) { station.m_repairItemDoneEffects.Create(((Component)station).transform.position, Quaternion.identity, (Transform)null, 1f, -1); ShowRepairMessage(player, num); } } } public static void Repair(Player player) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) if (Config.CraftingStationSearchRange > 0) { int range = Config.CraftingStationSearchRange; Vector3 origin = ((Component)player).transform.position; int repairCount = (from x in GetAllCraftingStations() let distance = Vector3.Distance(origin, ((Component)x).transform.position) where distance <= (float)range && x.CheckUsable(player, false) select RepairAll(player, x)).Sum(); ShowRepairMessage(player, repairCount); } } } internal static class Module { private static readonly Dictionary ItemRepairTimers; private static readonly Dictionary PieceRepairTimers; static Module() { ItemRepairTimers = new Dictionary(); PieceRepairTimers = new Dictionary(); } private static void Cleanup() { ItemRepairTimers.Clear(); PieceRepairTimers.Clear(); } [AutomaticsInitializer(5)] private static void Initialize() { Config.Initialize(); if (!Config.ModuleDisabled) { Hooks.OnPlayerAwake = (Action)Delegate.Combine(Hooks.OnPlayerAwake, (Action)delegate { Cleanup(); }); Hooks.OnPlayerFixedUpdate = (Action)Delegate.Combine(Hooks.OnPlayerFixedUpdate, new Action(OnPlayerFixedUpdate)); Harmony.CreateAndPatchAll(typeof(Patches), Automatics.GetHarmonyId("automatic-repair")); } } private static void OnPlayerFixedUpdate(Player player, float delta) { if (Config.EnableAutomaticRepair && !Game.IsPaused() && !((Object)(object)Player.m_localPlayer != (Object)(object)player) && ((Character)player).IsOwner()) { long playerID = player.GetPlayerID(); if (!ItemRepairTimers.TryGetValue(playerID, out var value)) { value = 0f; } value += delta; if (value >= 1f) { ItemRepairTimers[playerID] = 0f; ItemRepair.Repair(player); } else { ItemRepairTimers[playerID] = value; } if (!PieceRepairTimers.TryGetValue(playerID, out value)) { value = 0f; } value += delta; if (value >= 1f) { PieceRepairTimers[playerID] = 0f; PieceRepair.Repair(player); } else { PieceRepairTimers[playerID] = value; } } } } [HarmonyPatch] internal static class Patches { [HarmonyTranspiler] [HarmonyPatch(typeof(CraftingStation), "Interact")] public static IEnumerable CraftingStation_Interact_Transpiler(IEnumerable instructions) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Expected O, but got Unknown //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Expected O, but got Unknown //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Expected O, but got Unknown return new CodeMatcher(instructions, (ILGenerator)null).MatchStartForward((CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Callvirt, (object)AccessTools.Method(typeof(InventoryGui), "Show", (Type[])null, (Type[])null), (string)null) }).Advance(1).Insert((CodeInstruction[])(object)new CodeInstruction[3] { new CodeInstruction(OpCodes.Ldloc_0, (object)null), new CodeInstruction(OpCodes.Ldarg_0, (object)null), new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(ItemRepair), "CraftingStationInteractHook", (Type[])null, (Type[])null)) }) .InstructionEnumeration(); } } internal static class PieceRepair { private static readonly MethodInfo GetAllPiecesInRadiusMethod = AccessTools.DeclaredMethod(typeof(Piece), "GetAllPiecesInRadius", (Type[])null, (Type[])null); private static bool _skipRadiusMethodLookup; private static void ShowRepairMessage(Player player, int repairCount) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) if (repairCount != 0) { Automatics.Logger.Debug(() => $"Repaired {repairCount} pieces"); if (Config.PieceRepairMessage != 0) { MessageType val = (MessageType)((Config.PieceRepairMessage != Message.Center) ? 1 : 2); ((Character)player).Message(val, Automatics.L10N.Localize("@message_automatic_repair_repaired_the_pieces", repairCount), 0, (Sprite)null); } } } private static bool CheckCanRepairPiece(Player player, Piece piece) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) if (!player.NoCostCheat() && !((Object)(object)piece.m_craftingStation == (Object)null)) { return Object.op_Implicit((Object)(object)CraftingStation.HaveBuildStationInRange(piece.m_craftingStation.m_name, ((Component)player).transform.position)); } return true; } private static bool IsBuildTool(ItemData item) { return (Object)(object)item?.m_shared?.m_buildPieces != (Object)null; } private static bool TryGetBuildTool(Player player, out ItemData tool) { tool = Reflections.InvokeMethod(player, "GetRightItem"); if (IsBuildTool(tool)) { return true; } tool = Reflections.InvokeMethod(player, "GetLeftItem"); if (IsBuildTool(tool)) { return true; } tool = ((Humanoid)player).GetCurrentWeapon(); return IsBuildTool(tool); } private static object[] TryCreateRadiusMethodArguments(MethodInfo method, Vector3 origin, float range, List resultBuffer) { //IL_0043: Unknown result type (might be due to invalid IL or missing references) ParameterInfo[] parameters = method.GetParameters(); object[] array = new object[parameters.Length]; for (int i = 0; i < parameters.Length; i++) { Type type = parameters[i].ParameterType; if (type.IsByRef) { type = type.GetElementType(); } if (type == typeof(Vector3)) { array[i] = origin; continue; } if (type == typeof(float)) { array[i] = range; continue; } if (type != null && typeof(ICollection).IsAssignableFrom(type)) { array[i] = resultBuffer; continue; } if (type == null) { return null; } if (!type.IsValueType) { array[i] = null; } else { array[i] = Activator.CreateInstance(type); } } return array; } private static IEnumerable TryGetPiecesInRadius(Vector3 origin, float range) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) if (_skipRadiusMethodLookup || GetAllPiecesInRadiusMethod == null) { return null; } List list = new List(); try { object[] array = TryCreateRadiusMethodArguments(GetAllPiecesInRadiusMethod, origin, range, list); if (array == null) { _skipRadiusMethodLookup = true; return null; } if (GetAllPiecesInRadiusMethod.Invoke(null, array) is IEnumerable result) { return result; } return list; } catch (Exception ex) { Exception ex2 = ex; Exception e = ex2; _skipRadiusMethodLookup = true; Automatics.Logger.Debug(() => string.Format("Failed to query nearby pieces with {0}.{1}: {2}", "Piece", GetAllPiecesInRadiusMethod.Name, e)); return null; } } private static IEnumerable GetNearbyPieces(Vector3 origin, float range) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) IEnumerable enumerable = TryGetPiecesInRadius(origin, range); if (enumerable != null) { return enumerable; } HashSet hashSet = new HashSet(); Collider[] array = Physics.OverlapSphere(origin, range); for (int i = 0; i < array.Length; i++) { Piece componentInParent = ((Component)array[i]).GetComponentInParent(); if ((Object)(object)componentInParent != (Object)null) { hashSet.Add(componentInParent); } } return hashSet; } public static void Repair(Player player) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) if (Config.PieceSearchRange <= 0 || !TryGetBuildTool(player, out var tool)) { return; } SharedData shared = tool.m_shared; Vector3 position = ((Component)player).transform.position; int pieceSearchRange = Config.PieceSearchRange; int num = 0; foreach (Piece piece in GetNearbyPieces(position, pieceSearchRange)) { Vector3 position2 = ((Component)piece).transform.position; if (!PrivateArea.CheckAccess(position2, 0f, true, false) || !CheckCanRepairPiece(player, piece)) { continue; } WearNTear component = ((Component)piece).GetComponent(); if (!((Object)(object)component == (Object)null) && component.Repair()) { piece.m_placeEffect.Create(position2, ((Component)piece).transform.rotation, (Transform)null, 1f, -1); if (shared.m_useDurability) { ItemData obj = tool; obj.m_durability -= shared.m_useDurabilityDrain; } Automatics.Logger.Debug(() => $"Repair piece: [{piece.m_name}({Automatics.L10N.Translate(piece.m_name)}), pos: {((Component)piece).transform.position}]"); num++; } } if (num > 0) { ZSyncAnimation field = Reflections.GetField(player, "m_zanim"); if ((Object)(object)field != (Object)null) { field.SetTrigger(shared.m_attack.m_attackAnimation); } ShowRepairMessage(player, num); } } } } namespace Automatics.AutomaticProcessing { internal static class BeehiveProcess { public static bool Store(Beehive beehive, ZNetView zNetView, int increaseCount) { //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007b: 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_014b: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) if (!Config.EnableAutomaticProcessing) { return false; } if (!Objects.HasValidOwnership(zNetView)) { return false; } string name = beehive.m_name; if (!Logics.IsAllowProcessing(name, Process.Store)) { return false; } int num = zNetView.GetZDO().GetInt("level", 0) + increaseCount; if (num <= 0) { return false; } ItemDrop honeyItem = beehive.m_honeyItem; SharedData shared = honeyItem.m_itemData.m_shared; string name2 = shared.m_name; int worldLevel = honeyItem.m_itemData.m_worldLevel; int num2 = Config.ProductStacksOfSuppressProcessing(name); Vector3 position = ((Component)beehive).transform.position; int num3 = num; foreach (var nearbyContainer in Logics.GetNearbyContainers(name, position)) { Container item = nearbyContainer.container; if (num3 <= 0) { break; } Inventory inventory = item.GetInventory(); int num4 = inventory.CountItems(name2, -1, true); int num5 = num3; int num6 = num4 / shared.m_maxStackSize; if (num2 > 0) { if (num6 >= num2) { continue; } int num7 = inventory.FindFreeStackSpace(name2, (float)worldLevel); if (num7 == 0) { continue; } num5 = Mathf.Min(num5, num7); } if ((!Config.StoreOnlyIfProductExists(name) || Inventories.HaveItem(inventory, name2, 0f, WorldLevelMatchMode.Ignore, 1)) && inventory.AddItem(((Component)honeyItem).gameObject, num5)) { int num8 = inventory.CountItems(name2, -1, true) - num4; Logics.StoreLog(name2, num8, item.m_name, ((Component)item).transform.position, name, position); num3 -= num8; } } zNetView.GetZDO().Set("level", Mathf.Clamp(num3, 0, beehive.m_maxHoney)); return true; } } internal static class Config { private const string Section = "automatic_processing"; private static ConfigEntry _module; private static ConfigEntry _enableAutomaticProcessing; private static ConfigEntry _storageConnectionEffectColor; private static ConfigEntry _allowContainer; private static Dictionary> _allowProcessing; private static Dictionary> _containerSearchRange; private static Dictionary> _containerReferenceLimit; private static Dictionary> _materialCountOfSuppressProcessing; private static Dictionary> _supplyOnlyWhenMaterialsRunOut; private static Dictionary> _fuelCountOfSuppressProcessing; private static Dictionary> _productStacksOfSuppressProcessing; private static Dictionary> _refuelOnlyWhenMaterialsSupplied; private static Dictionary> _refuelOnlyWhenOutOfFuel; private static Dictionary> _storeOnlyIfProductExists; private static Dictionary> _numberOfItemsToStopCharge; public static bool ModuleDisabled => _module.Value == AutomaticsModule.Disabled; public static bool EnableAutomaticProcessing => _enableAutomaticProcessing.Value; public static Color StorageConnectionEffectColor { get { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) if (TryParseColor(_storageConnectionEffectColor.Value, out var color)) { return color; } return Color32.op_Implicit(new Color32((byte)79, (byte)169, byte.MaxValue, byte.MaxValue)); } } public static StringList AllowContainer => _allowContainer.Value; public static Process AllowProcessing(string processor) { if (!_allowProcessing.TryGetValue(processor, out var value)) { return Process.None; } return value.Value; } public static int ContainerSearchRange(string processor) { if (!_containerSearchRange.TryGetValue(processor, out var value)) { return 0; } return value.Value; } public static int ContainerReferenceLimit(string processor) { if (!_containerReferenceLimit.TryGetValue(processor, out var value)) { return 0; } return value.Value; } public static int MaterialCountOfSuppressProcessing(string processor) { if (!_materialCountOfSuppressProcessing.TryGetValue(processor, out var value)) { return 0; } return value.Value; } public static bool SupplyOnlyWhenMaterialsRunOut(string processor) { if (_supplyOnlyWhenMaterialsRunOut.TryGetValue(processor, out var value)) { return value.Value; } return false; } public static int FuelCountOfSuppressProcessing(string processor) { if (!_fuelCountOfSuppressProcessing.TryGetValue(processor, out var value)) { return 0; } return value.Value; } public static int ProductStacksOfSuppressProcessing(string processor) { if (!_productStacksOfSuppressProcessing.TryGetValue(processor, out var value)) { return 0; } return value.Value; } public static bool RefuelOnlyWhenMaterialsSupplied(string processor) { if (_refuelOnlyWhenMaterialsSupplied.TryGetValue(processor, out var value)) { return value.Value; } return false; } public static bool RefuelOnlyWhenOutOfFuel(string processor) { if (_refuelOnlyWhenOutOfFuel.TryGetValue(processor, out var value)) { return value.Value; } return false; } public static bool StoreOnlyIfProductExists(string processor) { if (_storeOnlyIfProductExists.TryGetValue(processor, out var value)) { return value.Value; } return false; } public static int NumberOfItemsToStopCharge(string processor) { if (!_numberOfItemsToStopCharge.TryGetValue(processor, out var value)) { return 0; } return value.Value; } public static void Initialize() { Configuration instance = global::Automatics.Config.Instance; instance.ChangeSection("automatic_processing"); _module = instance.Bind("module", AutomaticsModule.Enabled, null, delegate(ConfigurationManagerAttributes x) { x.DispName = Automatics.L10N.Translate("@config_common_disable_module_name"); x.Description = Automatics.L10N.Translate("@config_common_disable_module_description"); }); if (_module.Value == AutomaticsModule.Disabled) { return; } _enableAutomaticProcessing = instance.Bind("enable_automatic_processing", defaultValue: true); _storageConnectionEffectColor = instance.Bind("storage_connection_effect_color", "#4FA9FF", null, delegate(ConfigurationManagerAttributes x) { x.DispName = Automatics.L10N.Translate("@config_automatic_processing_storage_connection_effect_color_name"); x.Description = Automatics.L10N.Translate("@config_automatic_processing_storage_connection_effect_color_description"); }); _allowContainer = instance.BindValheimObjectList("allow_container", Globals.Container, null, null, new string[1] { "PieceChestPrivate" }); _allowProcessing = new Dictionary>(); _containerSearchRange = new Dictionary>(); _containerReferenceLimit = new Dictionary>(); _materialCountOfSuppressProcessing = new Dictionary>(); _supplyOnlyWhenMaterialsRunOut = new Dictionary>(); _fuelCountOfSuppressProcessing = new Dictionary>(); _productStacksOfSuppressProcessing = new Dictionary>(); _refuelOnlyWhenMaterialsSupplied = new Dictionary>(); _refuelOnlyWhenOutOfFuel = new Dictionary>(); _storeOnlyIfProductExists = new Dictionary>(); _numberOfItemsToStopCharge = new Dictionary>(); foreach (Processor item in Processor.GetAllInstance()) { string name = item.name; string displayName2 = Automatics.L10N.Translate(name); string text = name.Substring(1); Process defaultAllowedProcesses = item.defaultAllowedProcesses; Process[] array = item.processes.ToArray(); string key2 = "allow_processing_by_" + text; _allowProcessing[name] = instance.Bind(key2, defaultAllowedProcesses, (AcceptableValueBase)(object)new AcceptableValueEnum(array), Initializer("allow_processing_by", displayName2)); key2 = "container_search_range_by_" + text; _containerSearchRange[name] = instance.Bind(key2, 8, (1, 64), Initializer("container_search_range_by", displayName2)); key2 = "container_reference_limit_by_" + text; _containerReferenceLimit[name] = instance.Bind(key2, 0, (0, 999), Initializer("container_reference_limit_by", displayName2)); if (array.Contains(Process.Craft)) { key2 = text + "_material_count_of_suppress_processing"; _materialCountOfSuppressProcessing[name] = instance.Bind(key2, 1, (0, 999), Initializer("material_count_of_suppress_processing", displayName2)); key2 = text + "_product_stacks_of_suppress_processing"; _productStacksOfSuppressProcessing[name] = instance.Bind(key2, 0, (0, 99), Initializer("product_stacks_of_suppress_processing", displayName2)); key2 = text + "_supply_only_when_materials_run_out"; _supplyOnlyWhenMaterialsRunOut[name] = instance.Bind(key2, defaultValue: false, null, Initializer("supply_only_when_materials_run_out", displayName2)); } if (array.Contains(Process.Refuel)) { key2 = text + "_fuel_count_of_suppress_processing"; _fuelCountOfSuppressProcessing[name] = instance.Bind(key2, 1, (0, 999), Initializer("fuel_count_of_suppress_processing", displayName2)); key2 = text + "_refuel_only_when_out_of_fuel"; _refuelOnlyWhenOutOfFuel[name] = instance.Bind(key2, defaultValue: false, null, Initializer("refuel_only_when_out_of_fuel", displayName2)); } if (array.Contains(Process.Refuel) && array.Contains(Process.Craft)) { key2 = text + "_refuel_only_when_materials_supplied"; _refuelOnlyWhenMaterialsSupplied[name] = instance.Bind(key2, defaultValue: false, null, Initializer("refuel_only_when_materials_supplied", displayName2)); } if (array.Contains(Process.Store)) { key2 = text + "_store_only_if_product_exists"; _storeOnlyIfProductExists[name] = instance.Bind(key2, defaultValue: false, null, Initializer("store_only_if_product_exists", displayName2)); } if (array.Contains(Process.Charge)) { key2 = text + "_number_of_items_to_stop_charge"; _numberOfItemsToStopCharge[name] = instance.Bind(key2, 1, (0, 999), Initializer("number_of_items_to_stop_charge", displayName2)); } } instance.ChangeSection("general", 192); instance.BindCustomValheimObject("custom_container", Globals.Container); static Action Initializer(string key, string displayName) { return delegate(ConfigurationManagerAttributes x) { x.DispName = Automatics.L10N.Localize("@config_automatic_processing_" + key + "_name", displayName); x.Description = Automatics.L10N.Localize("@config_automatic_processing_" + key + "_description", displayName); }; } } private static bool TryParseColor(string value, out Color color) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) color = default(Color); if (string.IsNullOrWhiteSpace(value)) { return false; } string text = value.Trim(); if (!text.StartsWith("#", StringComparison.Ordinal)) { text = "#" + text; } return ColorUtility.TryParseHtmlString(text, ref color); } } internal static class ConnectionEffects { private readonly struct ProcessorContext { public int Id { get; } public string Name { get; } public Vector3 SearchOrigin { get; } public Vector3 EffectPoint { get; } public ProcessorContext(int id, string name, Vector3 searchOrigin, Vector3 effectPoint) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) Id = id; Name = name; SearchOrigin = searchOrigin; EffectPoint = effectPoint; } } private sealed class ConnectionHelper { public GameObject Root { get; } public GameObject Connection { get; set; } public GameObject ConnectionPrefab { get; } public Vector3 ConnectionOffset { get; } public bool ColorApplied { get; set; } public Color LastAppliedColor { get; set; } public ConnectionHelper(GameObject root, GameObject connectionPrefab, Vector3 connectionOffset) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) Root = root; ConnectionPrefab = connectionPrefab; ConnectionOffset = connectionOffset; } } private sealed class ConnectionTemplate { public GameObject ConnectionPrefab { get; } public Vector3 ConnectionOffset { get; } public ConnectionTemplate(GameObject connectionPrefab, Vector3 connectionOffset) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) ConnectionPrefab = connectionPrefab; ConnectionOffset = connectionOffset; } public static implicit operator bool(ConnectionTemplate template) { if (template != null) { return Object.op_Implicit((Object)(object)template.ConnectionPrefab); } return false; } } private static readonly int ColorPropertyId; private static readonly int TintColorPropertyId; private static readonly int EmissionColorPropertyId; private const float RefreshInterval = 0.75f; private const float FireplaceEffectHeight = 1.2f; private const float TurretEffectHeight = 1.4f; private const float ContainerTopInset = 0.05f; private static readonly Dictionary ActiveHelpers; private static int _currentProcessorId; private static float _nextRefreshTime; private static ConnectionTemplate _template; static ConnectionEffects() { ColorPropertyId = Shader.PropertyToID("_Color"); TintColorPropertyId = Shader.PropertyToID("_TintColor"); EmissionColorPropertyId = Shader.PropertyToID("_EmissionColor"); ActiveHelpers = new Dictionary(); } public static void Cleanup() { foreach (int item in ActiveHelpers.Keys.ToList()) { RemoveHelper(item); } ActiveHelpers.Clear(); _currentProcessorId = 0; _nextRefreshTime = 0f; } public static void Update(Player player) { if (!Config.EnableAutomaticProcessing || Game.IsPaused()) { Cleanup(); return; } GameObject field = Reflections.GetField(player, "m_hovering"); ProcessorContext context; if (!Object.op_Implicit((Object)(object)field)) { Cleanup(); } else if (!TryGetProcessorContext(field, out context)) { Cleanup(); } else if ((float)Config.ContainerSearchRange(context.Name) <= 0f || !HasSourceProcess(context.Name)) { Cleanup(); } else if (_currentProcessorId != context.Id || Time.time >= _nextRefreshTime) { Refresh(context); } } private static bool HasSourceProcess(string processorName) { return (Config.AllowProcessing(processorName) & (Process.Craft | Process.Refuel | Process.Charge)) != 0; } private static void Refresh(ProcessorContext context) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) ConnectionTemplate template = GetTemplate(); if (!template) { Cleanup(); return; } HashSet activeIds = new HashSet(); foreach (var nearbyContainer in Logics.GetNearbyContainers(context.Name, context.SearchOrigin)) { Container item = nearbyContainer.container; if (!Object.op_Implicit((Object)(object)item)) { continue; } int instanceID = ((Object)item).GetInstanceID(); activeIds.Add(instanceID); if (!ActiveHelpers.TryGetValue(instanceID, out var value) || (Object)(object)value.Root == (Object)null || !Object.op_Implicit((Object)(object)value.ConnectionPrefab)) { value = CreateHelper(template, item); if (value == null) { continue; } ActiveHelpers[instanceID] = value; } PositionHelper(value, item); UpdateConnectionEffect(value, context.EffectPoint); } foreach (int item2 in ActiveHelpers.Keys.Where((int x) => !activeIds.Contains(x)).ToList()) { RemoveHelper(item2); } _currentProcessorId = context.Id; _nextRefreshTime = Time.time + 0.75f; } private static void RemoveHelper(int containerId) { if (ActiveHelpers.TryGetValue(containerId, out var value)) { if (Object.op_Implicit((Object)(object)value.Connection)) { Object.Destroy((Object)(object)value.Connection); } if (Object.op_Implicit((Object)(object)value.Root)) { Object.Destroy((Object)(object)value.Root); } ActiveHelpers.Remove(containerId); } } private static ConnectionHelper CreateHelper(ConnectionTemplate template, Container container) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_0040: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("Automatics_StorageConnectionHelper"); if (!Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)template.ConnectionPrefab)) { if (Object.op_Implicit((Object)(object)val)) { Object.Destroy((Object)(object)val); } return null; } ((Object)val).hideFlags = (HideFlags)61; ConnectionHelper connectionHelper = new ConnectionHelper(val, template.ConnectionPrefab, template.ConnectionOffset); PositionHelper(connectionHelper, container); return connectionHelper; } private static void PositionHelper(ConnectionHelper helper, Container container) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0012: 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_0019: 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) Vector3 containerConnectionPoint = GetContainerConnectionPoint(container); helper.Root.transform.SetPositionAndRotation(containerConnectionPoint - helper.ConnectionOffset, Quaternion.identity); } private static Vector3 GetContainerConnectionPoint(Container container) { //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_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_000c: 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_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) if (TryGetContainerBounds(container, out var bounds)) { float num = Mathf.Max(((Bounds)(ref bounds)).min.y, ((Bounds)(ref bounds)).max.y - 0.05f); return new Vector3(((Bounds)(ref bounds)).center.x, num, ((Bounds)(ref bounds)).center.z); } return ((Component)container).transform.position + Vector3.up * 0.5f; } private static bool TryGetContainerBounds(Container container, out Bounds bounds) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_007b: 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) bool flag = false; bounds = default(Bounds); Renderer[] componentsInChildren = ((Component)container).GetComponentsInChildren(); foreach (Renderer val in componentsInChildren) { if (val.enabled) { if (!flag) { bounds = val.bounds; flag = true; } else { ((Bounds)(ref bounds)).Encapsulate(val.bounds); } } } Collider[] componentsInChildren2 = ((Component)container).GetComponentsInChildren(); foreach (Collider val2 in componentsInChildren2) { if (val2.enabled) { if (!flag) { bounds = val2.bounds; flag = true; } else { ((Bounds)(ref bounds)).Encapsulate(val2.bounds); } } } return flag; } private static void UpdateConnectionEffect(ConnectionHelper helper, Vector3 effectPoint) { //IL_000c: 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) //IL_0016: 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_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0019: 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_0060: 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_0068: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) Vector3 val = helper.Root.transform.TransformPoint(helper.ConnectionOffset); Vector3 val2 = effectPoint - val; float magnitude = ((Vector3)(ref val2)).magnitude; if (!(magnitude <= Mathf.Epsilon)) { if (!Object.op_Implicit((Object)(object)helper.Connection)) { helper.Connection = Object.Instantiate(helper.ConnectionPrefab, val, Quaternion.identity); } Transform transform = helper.Connection.transform; transform.SetPositionAndRotation(val, Quaternion.LookRotation(((Vector3)(ref val2)).normalized)); transform.localScale = new Vector3(1f, 1f, magnitude); ApplyConnectionColor(helper, Config.StorageConnectionEffectColor); } } private static void ApplyConnectionColor(ConnectionHelper helper, Color color) { //IL_0017: 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_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006b: 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_0098: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)helper.Connection) || (helper.ColorApplied && helper.LastAppliedColor == color)) { return; } LineRenderer[] componentsInChildren = helper.Connection.GetComponentsInChildren(true); foreach (LineRenderer obj in componentsInChildren) { obj.startColor = color; obj.endColor = color; } TrailRenderer[] componentsInChildren2 = helper.Connection.GetComponentsInChildren(true); foreach (TrailRenderer obj2 in componentsInChildren2) { obj2.startColor = color; obj2.endColor = color; } ParticleSystem[] componentsInChildren3 = helper.Connection.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren3.Length; i++) { MainModule main = componentsInChildren3[i].main; ((MainModule)(ref main)).startColor = MinMaxGradient.op_Implicit(color); } Renderer[] componentsInChildren4 = helper.Connection.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren4.Length; i++) { Material[] materials = componentsInChildren4[i].materials; foreach (Material val in materials) { if (val.HasProperty(ColorPropertyId)) { val.SetColor(ColorPropertyId, color); } if (val.HasProperty(TintColorPropertyId)) { val.SetColor(TintColorPropertyId, color); } if (val.HasProperty(EmissionColorPropertyId)) { val.SetColor(EmissionColorPropertyId, color); } } } helper.LastAppliedColor = color; helper.ColorApplied = true; } private static ConnectionTemplate GetTemplate() { //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) if ((bool)_template) { return _template; } if (!Object.op_Implicit((Object)(object)ZNetScene.instance)) { return null; } ConnectionTemplate connectionTemplate = null; foreach (GameObject prefab in ZNetScene.instance.m_prefabs) { if (!Object.op_Implicit((Object)(object)prefab)) { continue; } StationExtension val = ((IEnumerable)prefab.GetComponentsInChildren(true)).FirstOrDefault((Func)((StationExtension x) => Object.op_Implicit((Object)(object)x) && Object.op_Implicit((Object)(object)x.m_connectionPrefab) && Object.op_Implicit((Object)(object)((Component)x).GetComponent()))); if (Object.op_Implicit((Object)(object)val)) { if (!connectionTemplate) { connectionTemplate = new ConnectionTemplate(val.m_connectionPrefab, val.m_connectionOffset); } if (Object.op_Implicit((Object)(object)val.m_craftingStation) && val.m_craftingStation.m_name == "$piece_forge") { _template = new ConnectionTemplate(val.m_connectionPrefab, val.m_connectionOffset); return _template; } } } _template = connectionTemplate; return _template; } private static bool TryGetProcessorContext(GameObject hovering, out ProcessorContext context) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //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_009e: 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_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0042: 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) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: 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_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: 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_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_01b8: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_01c6: Unknown result type (might be due to invalid IL or missing references) //IL_01cb: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0115: 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_0168: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) Smelter componentInParent = hovering.GetComponentInParent(); if (Object.op_Implicit((Object)(object)componentInParent)) { Vector3 position = ((Component)componentInParent).transform.position; Vector3 effectPoint = (Object.op_Implicit((Object)(object)componentInParent.m_outputPoint) ? componentInParent.m_outputPoint.position : (position + Vector3.up)); context = new ProcessorContext(((Object)componentInParent).GetInstanceID(), componentInParent.m_name, position, effectPoint); return true; } CookingStation componentInParent2 = hovering.GetComponentInParent(); if (Object.op_Implicit((Object)(object)componentInParent2)) { Vector3 position2 = ((Component)componentInParent2).transform.position; Vector3 effectPoint2 = (Object.op_Implicit((Object)(object)componentInParent2.m_spawnPoint) ? componentInParent2.m_spawnPoint.position : (position2 + Vector3.up)); context = new ProcessorContext(((Object)componentInParent2).GetInstanceID(), componentInParent2.m_name, position2, effectPoint2); return true; } Fermenter componentInParent3 = hovering.GetComponentInParent(); if (Object.op_Implicit((Object)(object)componentInParent3)) { Vector3 position3 = ((Component)componentInParent3).transform.position; Vector3 effectPoint3 = (Object.op_Implicit((Object)(object)componentInParent3.m_outputPoint) ? componentInParent3.m_outputPoint.position : (position3 + Vector3.up)); context = new ProcessorContext(((Object)componentInParent3).GetInstanceID(), componentInParent3.m_name, position3, effectPoint3); return true; } Fireplace componentInParent4 = hovering.GetComponentInParent(); if (Object.op_Implicit((Object)(object)componentInParent4)) { Vector3 position4 = ((Component)componentInParent4).transform.position; Piece component = ((Component)componentInParent4).GetComponent(); context = new ProcessorContext(((Object)componentInParent4).GetInstanceID(), Object.op_Implicit((Object)(object)component) ? component.m_name : componentInParent4.m_name, position4, position4 + Vector3.up * 1.2f); return true; } Turret componentInParent5 = hovering.GetComponentInParent(); if (Object.op_Implicit((Object)(object)componentInParent5)) { Vector3 position5 = ((Component)componentInParent5).transform.position; context = new ProcessorContext(((Object)componentInParent5).GetInstanceID(), componentInParent5.m_name, position5, position5 + Vector3.up * 1.4f); return true; } context = default(ProcessorContext); return false; } } internal static class CookingStationProcess { private static bool IsFireLit(CookingStation cookingStation) { return Reflections.InvokeMethod(cookingStation, "IsFireLit"); } private static ItemConversion GetItemConversion(CookingStation cookingStation, string item) { return Reflections.InvokeMethod(cookingStation, "GetItemConversion", new object[1] { item }); } public static void Craft(CookingStation cookingStation, ZNetView zNetView) { //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_02e0: Unknown result type (might be due to invalid IL or missing references) //IL_02e6: Unknown result type (might be due to invalid IL or missing references) if (!Config.EnableAutomaticProcessing || !Objects.HasValidOwnership(zNetView)) { return; } string name = cookingStation.m_name; if (!Logics.IsAllowProcessing(name, Process.Craft) || (cookingStation.m_requireFire && !IsFireLit(cookingStation)) || (cookingStation.m_useFuel && zNetView.GetZDO().GetFloat("fuel", 0f) <= 0f)) { return; } Dictionary dictionary = new Dictionary(); int num = 0; int num2 = cookingStation.m_slots.Length; for (int i = 0; i < num2; i++) { string @string = zNetView.GetZDO().GetString("slot" + i, ""); if (string.IsNullOrEmpty(@string)) { num++; } else if (!(@string == ((Object)cookingStation.m_overCookedItem).name)) { ItemConversion itemConversion = GetItemConversion(cookingStation, @string); if (itemConversion != null) { string name2 = itemConversion.m_to.m_itemData.m_shared.m_name; dictionary[name2] = ((!dictionary.TryGetValue(name2, out var value)) ? 1 : (value + 1)); } } } if (num == 0 || (Config.SupplyOnlyWhenMaterialsRunOut(name) && num != num2)) { return; } int num3 = Config.MaterialCountOfSuppressProcessing(name); int num4 = Config.ProductStacksOfSuppressProcessing(name); Vector3 position = ((Component)cookingStation).transform.position; List<(Container, Inventory)> list = (from x in Logics.GetNearbyContainers(name, position) select (x.container, x.container.GetInventory())).ToList(); foreach (ItemConversion item2 in cookingStation.m_conversion) { Container val = null; bool flag = false; SharedData shared = item2.m_from.m_itemData.m_shared; ItemData itemData = item2.m_to.m_itemData; SharedData shared2 = itemData.m_shared; foreach (var (val2, val3) in list) { if (Object.op_Implicit((Object)(object)val) && flag) { break; } if ((Object)(object)val == (Object)null && Inventories.HaveItem(val3, shared.m_name, 0f, WorldLevelMatchMode.Ignore, num3 + 1)) { val = val2; } if (num4 > 0 && !flag) { if (!dictionary.TryGetValue(shared2.m_name, out var value2)) { value2 = 0; } if ((val3.CountItems(shared2.m_name, -1, true) + value2) / shared2.m_maxStackSize < num4) { flag = val3.CanAddItem(itemData, 1); } } } if (Object.op_Implicit((Object)(object)val) && (num4 == 0 || flag)) { ItemData item = val.GetInventory().GetItem(shared.m_name, -1, false); val.GetInventory().RemoveOneItem(item); zNetView.InvokeRPC("RPC_AddItem", new object[1] { ((Object)item.m_dropPrefab).name }); Logics.CraftingLog(shared.m_name, 1, val.m_name, ((Component)val).transform.position, name, position, shared2.m_name); break; } } } [UsedImplicitly] public static float Refuel(CookingStation cookingStation, ZNetView zNetView, float fuel) { //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0076: 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_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) if (!Config.EnableAutomaticProcessing) { return fuel; } if (!Objects.HasValidOwnership(zNetView)) { return fuel; } if (fuel > (float)cookingStation.m_maxFuel - 1f) { return fuel; } string name = cookingStation.m_name; if (!Logics.IsAllowProcessing(name, Process.Refuel)) { return fuel; } if (Config.RefuelOnlyWhenOutOfFuel(name) && fuel > 0f) { return fuel; } if (Config.RefuelOnlyWhenMaterialsSupplied(name) && Reflections.InvokeMethod(cookingStation, "GetFreeSlot") < 0) { return fuel; } int num = Config.FuelCountOfSuppressProcessing(name); Transform transform = ((Component)cookingStation).transform; Vector3 position = transform.position; string name2 = cookingStation.m_fuelItem.m_itemData.m_shared.m_name; foreach (var nearbyContainer in Logics.GetNearbyContainers(name, position)) { Container item = nearbyContainer.container; Inventory inventory = item.GetInventory(); if (Inventories.HaveItem(inventory, name2, 0f, WorldLevelMatchMode.Ignore, num + 1)) { inventory.RemoveItem(name2, 1, -1, true); fuel += 1f; cookingStation.m_fuelAddedEffects.Create(position, transform.rotation, transform, 1f, -1); Logics.RefuelLog(name2, 1, name, position, item.m_name, ((Component)item).transform.position); break; } } return fuel; } [UsedImplicitly] public static bool Store(CookingStation cookingStation, ZNetView zNetView, int slot, ItemConversion conversion) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) if (!Config.EnableAutomaticProcessing) { return false; } if (!Objects.HasValidOwnership(zNetView)) { return false; } string name = cookingStation.m_name; if (!Logics.IsAllowProcessing(name, Process.Store)) { return false; } ItemDrop to = conversion.m_to; string name2 = to.m_itemData.m_shared.m_name; Vector3 position = ((Component)cookingStation).transform.position; foreach (var nearbyContainer in Logics.GetNearbyContainers(name, position)) { Container item = nearbyContainer.container; Inventory inventory = item.GetInventory(); if ((!Config.StoreOnlyIfProductExists(name) || Inventories.HaveItem(inventory, name2, 0f, WorldLevelMatchMode.Ignore, 1)) && inventory.AddItem(((Component)to).gameObject, 1)) { zNetView.GetZDO().Set("slot" + slot, ""); zNetView.GetZDO().Set("slot" + slot, 0f); zNetView.GetZDO().Set("slotstatus" + slot, 0); zNetView.InvokeRPC(ZNetView.Everybody, "RPC_SetSlotVisual", new object[2] { slot, "" }); Logics.StoreLog(name2, 1, item.m_name, ((Component)item).transform.position, name, position); return true; } } return false; } } internal static class FermenterProcess { private enum Status { Empty, Fermenting, Exposed, Ready } private static Status GetStatus(Fermenter fermenter) { int num = Reflections.InvokeMethod(fermenter, "GetStatus"); return num switch { 0 => Status.Empty, 1 => Status.Fermenting, 2 => Status.Exposed, 3 => Status.Ready, _ => throw new Exception($"Illegal Fermenter status: {num}"), }; } public static void Craft(Fermenter fermenter, ZNetView zNetView) { //IL_004e: 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_0055: 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) //IL_01f1: Unknown result type (might be due to invalid IL or missing references) if (!Config.EnableAutomaticProcessing || !Objects.HasValidOwnership(zNetView)) { return; } string name = fermenter.m_name; if (!Logics.IsAllowProcessing(name, Process.Craft) || GetStatus(fermenter) != 0 || Reflections.GetField(fermenter, "m_exposed")) { return; } int num = Config.MaterialCountOfSuppressProcessing(name); int num2 = Config.ProductStacksOfSuppressProcessing(name); Vector3 position = ((Component)fermenter).transform.position; List<(Container, Inventory)> list = (from x in Logics.GetNearbyContainers(name, position) select (x.container, x.container.GetInventory())).ToList(); foreach (ItemConversion item2 in fermenter.m_conversion) { Container val = null; bool flag = false; SharedData shared = item2.m_from.m_itemData.m_shared; ItemData itemData = item2.m_to.m_itemData; SharedData shared2 = itemData.m_shared; foreach (var (val2, val3) in list) { if (Object.op_Implicit((Object)(object)val) && flag) { break; } if ((Object)(object)val == (Object)null && Inventories.HaveItem(val3, shared.m_name, 0f, WorldLevelMatchMode.Ignore, num + 1)) { val = val2; } if (num2 > 0 && !flag && val3.CountItems(shared2.m_name, -1, true) / shared2.m_maxStackSize < num2) { flag = val3.CanAddItem(itemData, item2.m_producedItems); } } if (Object.op_Implicit((Object)(object)val) && (num2 == 0 || flag)) { ItemData item = val.GetInventory().GetItem(shared.m_name, -1, false); val.GetInventory().RemoveOneItem(item); zNetView.InvokeRPC("RPC_AddItem", new object[1] { ((Object)item.m_dropPrefab).name }); Logics.CraftingLog(shared.m_name, 1, val.m_name, ((Component)val).transform.position, name, position, shared2.m_name); break; } } } public static void Store(Fermenter fermenter, ZNetView zNetView) { //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Unknown result type (might be due to invalid IL or missing references) //IL_019e: 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_0130: Unknown result type (might be due to invalid IL or missing references) //IL_01b8: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_01d9: Unknown result type (might be due to invalid IL or missing references) //IL_01db: Unknown result type (might be due to invalid IL or missing references) if (!Config.EnableAutomaticProcessing || !Objects.HasValidOwnership(zNetView)) { return; } string name = fermenter.m_name; if (!Logics.IsAllowProcessing(name, Process.Store) || GetStatus(fermenter) != Status.Ready) { return; } string itemId = zNetView.GetZDO().GetString("Content", ""); ItemConversion val = ((IEnumerable)fermenter.m_conversion).FirstOrDefault((Func)((ItemConversion x) => ((Object)((Component)x.m_from).gameObject).name == itemId)); if (val == null) { return; } Vector3 position = ((Component)fermenter).transform.position; ItemDrop to = val.m_to; string name2 = to.m_itemData.m_shared.m_name; int num = val.m_producedItems; foreach (var nearbyContainer in Logics.GetNearbyContainers(name, position)) { Container item = nearbyContainer.container; if (num <= 0) { break; } Inventory inventory = item.GetInventory(); int num2 = inventory.CountItems(name2, -1, true); if ((!Config.StoreOnlyIfProductExists(name) || Inventories.HaveItem(inventory, name2, 0f, WorldLevelMatchMode.Ignore, 1)) && inventory.AddItem(((Component)to).gameObject, num)) { int num3 = inventory.CountItems(name2, -1, true) - num2; Logics.StoreLog(name2, num3, item.m_name, ((Component)item).transform.position, name, position); num -= num3; } } if (num != val.m_producedItems) { zNetView.GetZDO().Set("Content", ""); zNetView.GetZDO().Set("StartTime", 0); fermenter.m_spawnEffects.Create(((Component)fermenter.m_outputPoint).transform.position, Quaternion.identity, (Transform)null, 1f, -1); while (num > 0) { Vector3 val2 = fermenter.m_outputPoint.position + Vector3.up * 0.3f; Object.Instantiate(val.m_to, val2, Quaternion.identity); num--; } } } } internal static class FireplaceProcess { [UsedImplicitly] public static void Refuel(Fireplace fire, Piece piece, ZNetView zNetView) { //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) if (!Config.EnableAutomaticProcessing || !Objects.HasValidOwnership(zNetView) || fire.m_infiniteFuel) { return; } string name = piece.m_name; if (!Logics.IsAllowProcessing(name, Process.Refuel)) { return; } float @float = zNetView.GetZDO().GetFloat("fuel", 0f); if ((float)Mathf.CeilToInt(@float) >= fire.m_maxFuel || (Config.RefuelOnlyWhenOutOfFuel(name) && @float > 0f)) { return; } int num = Config.FuelCountOfSuppressProcessing(name); Vector3 position = ((Component)fire).transform.position; string name2 = fire.m_fuelItem.m_itemData.m_shared.m_name; foreach (var nearbyContainer in Logics.GetNearbyContainers(name, position)) { Container item = nearbyContainer.container; Inventory inventory = item.GetInventory(); if (Inventories.HaveItem(inventory, name2, 0f, WorldLevelMatchMode.Ignore, num + 1)) { inventory.RemoveItem(name2, 1, -1, true); zNetView.InvokeRPC("RPC_AddFuel", Array.Empty()); Logics.RefuelLog(name2, 1, name, position, item.m_name, ((Component)item).transform.position); break; } } } } internal static class Globals { public static ValheimObject Container { get; } = new ValheimObject("container"); } internal static class Logics { private static readonly Dictionary> Containers; private static float _lastContainersReset; static Logics() { Containers = new Dictionary>(); } public static void Cleanup() { Containers.Clear(); _lastContainersReset = 0f; } public static void CraftingLog(string materialName, int count, string fromName, Vector3 fromPos, string toName, Vector3 toPos, string productName) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) Automatics.Logger.Debug(() => $"{Automatics.L10N.Translate(materialName)} x{count} was set from {Automatics.L10N.Translate(fromName)}{fromPos} to {Automatics.L10N.Translate(toName)}{toPos} for crafting {Automatics.L10N.Translate(productName)}"); } public static void RefuelLog(string fuelName, int count, string toName, Vector3 toPos, string fromName, Vector3 fromPos) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) Automatics.Logger.Debug(() => $"Refueled {Automatics.L10N.Translate(fuelName)} x{count} in {Automatics.L10N.Translate(toName)}{toPos} from {Automatics.L10N.Translate(fromName)}{fromPos}"); } public static void StoreLog(string productName, int count, string toName, Vector3 toPos, string fromName, Vector3 fromPos) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) Automatics.Logger.Debug(() => $"Stored {Automatics.L10N.Translate(productName)} x{count} in {Automatics.L10N.Translate(toName)}{toPos} from {Automatics.L10N.Translate(fromName)}{fromPos}"); } public static void ChargeLog(string itemName, int count, string toName, Vector3 toPos, string fromName, Vector3 fromPos) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) Automatics.Logger.Debug(() => $"Charge {Automatics.L10N.Translate(itemName)} x{count} to {Automatics.L10N.Translate(toName)}{toPos} from {Automatics.L10N.Translate(fromName)}{fromPos}"); } public static bool IsAllowContainer(Container container) { if (Globals.Container.GetIdentify(Objects.GetName((Component)(object)container), out var identifier)) { return Config.AllowContainer.Contains(identifier); } return false; } public static bool IsAllowProcessing(string target, Process type) { return (Config.AllowProcessing(target) & type) != 0; } public static IEnumerable<(Container container, float distance)> GetNearbyContainers(string target, Vector3 origin) { //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) if (Time.time - _lastContainersReset > 1f) { _lastContainersReset = Time.time; Containers.Clear(); } int range = Config.ContainerSearchRange(target); int num = Config.ContainerReferenceLimit(target); string key = target + ":" + ((object)(Vector3)(ref origin)).GetHashCode() + ":" + range + ":" + num; if (Containers.TryGetValue(key, out List<(Container, float)> value)) { return value.Where<(Container, float)>(((Container container, float distance) x) => Object.op_Implicit((Object)(object)x.container)); } List<(Container, float)> list = new List<(Container, float)>(); Containers[key] = list; if (range > 0) { list.AddRange((from x in InstanceCache.GetAllInstance() let distance = Vector3.Distance(origin, ((Component)x).transform.position) where distance <= (float)range && IsAllowContainer(x) orderby distance select (x, distance)).Take((num > 0) ? num : int.MaxValue)); } return list; } } internal static class Module { [AutomaticsInitializer(3)] private static void Initialize() { Config.Initialize(); if (!Config.ModuleDisabled) { Hooks.OnPlayerAwake = (Action)Delegate.Combine(Hooks.OnPlayerAwake, (Action)delegate { Logics.Cleanup(); SmelterProcess.Cleanup(); ConnectionEffects.Cleanup(); }); Hooks.OnPlayerUpdate = (Action)Delegate.Combine(Hooks.OnPlayerUpdate, new Action(OnPlayerUpdate)); Harmony.CreateAndPatchAll(typeof(Patches), Automatics.GetHarmonyId("automatic-processing")); } } private static void OnPlayerUpdate(Player player, bool takeInput) { if (!((Object)(object)Player.m_localPlayer != (Object)(object)player) && ((Character)player).IsOwner()) { ConnectionEffects.Update(player); } } } [HarmonyPatch] internal static class Patches { [HarmonyPrefix] [HarmonyPatch(typeof(Beehive), "IncreseLevel")] private static bool Beehive_IncreseLevel_Prefix(Beehive __instance, ZNetView ___m_nview, int i) { return !BeehiveProcess.Store(__instance, ___m_nview, i); } [HarmonyTranspiler] [HarmonyPatch(typeof(CookingStation), "UpdateFuel")] public static IEnumerable CookingStation_UpdateFuel_Transpiler(IEnumerable instructions) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Expected O, but got Unknown //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Expected O, but got Unknown //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Expected O, but got Unknown //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Expected O, but got Unknown //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Expected O, but got Unknown //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Expected O, but got Unknown //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Expected O, but got Unknown //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Expected O, but got Unknown return new CodeMatcher(instructions, (ILGenerator)null).MatchStartForward((CodeMatch[])(object)new CodeMatch[3] { new CodeMatch((OpCode?)OpCodes.Ldarg_0, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Ldloc_1, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Call, (object)AccessTools.Method(typeof(CookingStation), "SetFuel", (Type[])null, (Type[])null), (string)null) }).Advance(1).Insert((CodeInstruction[])(object)new CodeInstruction[6] { new CodeInstruction(OpCodes.Ldarg_0, (object)null), new CodeInstruction(OpCodes.Ldfld, (object)AccessTools.Field(typeof(CookingStation), "m_nview")), new CodeInstruction(OpCodes.Ldloc_1, (object)null), new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(CookingStationProcess), "Refuel", (Type[])null, (Type[])null)), new CodeInstruction(OpCodes.Stloc_1, (object)null), new CodeInstruction(OpCodes.Ldarg_0, (object)null) }) .InstructionEnumeration(); } [HarmonyTranspiler] [HarmonyPatch(typeof(CookingStation), "UpdateCooking")] public static IEnumerable CookingStation_UpdateCooking_Transpiler(IEnumerable instructions) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Expected O, but got Unknown //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Expected O, but got Unknown //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Expected O, but got Unknown //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Expected O, but got Unknown //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Expected O, but got Unknown //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Expected O, but got Unknown CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null).MatchEndForward((CodeMatch[])(object)new CodeMatch[3] { new CodeMatch((OpCode?)OpCodes.Ldc_I4_2, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Call, (object)AccessTools.Method(typeof(CookingStation), "SetSlot", (Type[])null, (Type[])null), (string)null), new CodeMatch((OpCode?)OpCodes.Br, (object)null, (string)null) }); object operand = val.Operand; InsertCodes(val.MatchStartBackwards((CodeMatch[])(object)new CodeMatch[2] { new CodeMatch((OpCode?)OpCodes.Ldarg_0, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Ldfld, (object)AccessTools.Field(typeof(CookingStation), "m_overcookedEffect"), (string)null) }), operand); InsertCodes(val.MatchStartForward((CodeMatch[])(object)new CodeMatch[2] { new CodeMatch((OpCode?)OpCodes.Ldarg_0, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Ldfld, (object)AccessTools.Field(typeof(CookingStation), "m_doneEffect"), (string)null) }), operand); return val.InstructionEnumeration(); static void InsertCodes(CodeMatcher codeMatcher, object label) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Expected O, but got Unknown //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Expected O, but got Unknown //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Expected O, but got Unknown //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Expected O, but got Unknown //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Expected O, but got Unknown codeMatcher.Insert((CodeInstruction[])(object)new CodeInstruction[7] { new CodeInstruction(OpCodes.Ldarg_0, (object)null), new CodeInstruction(OpCodes.Ldarg_0, (object)null), new CodeInstruction(OpCodes.Ldfld, (object)AccessTools.Field(typeof(CookingStation), "m_nview")), new CodeInstruction(OpCodes.Ldloc_2, (object)null), new CodeInstruction(OpCodes.Ldloc_S, (object)6), new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(CookingStationProcess), "Store", (Type[])null, (Type[])null)), new CodeInstruction(OpCodes.Brtrue_S, label) }); } } [HarmonyPostfix] [HarmonyPatch(typeof(CookingStation), "UpdateCooking")] private static void CookingStation_UpdateCooking_Postfix(CookingStation __instance, ZNetView ___m_nview) { CookingStationProcess.Craft(__instance, ___m_nview); } [HarmonyPostfix] [HarmonyPatch(typeof(Fermenter), "SlowUpdate")] private static void Fermenter_SlowUpdate_Postfix(Fermenter __instance, ZNetView ___m_nview) { FermenterProcess.Store(__instance, ___m_nview); FermenterProcess.Craft(__instance, ___m_nview); } [HarmonyPostfix] [HarmonyPatch(typeof(Fireplace), "UpdateFireplace")] private static void Fireplace_UpdateFireplace_Postfix(Fireplace __instance, Piece ___m_piece, ZNetView ___m_nview) { FireplaceProcess.Refuel(__instance, ___m_piece, ___m_nview); } [HarmonyTranspiler] [HarmonyPatch(typeof(Smelter), "UpdateSmelter")] public static IEnumerable Smelter_UpdateSmelter_Transpiler(IEnumerable instructions) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Expected O, but got Unknown //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Expected O, but got Unknown //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Expected O, but got Unknown //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Expected O, but got Unknown //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Expected O, but got Unknown //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Expected O, but got Unknown //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Expected O, but got Unknown //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Expected O, but got Unknown //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Expected O, but got Unknown //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Expected O, but got Unknown //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Expected O, but got Unknown //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Expected O, but got Unknown //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Expected O, but got Unknown //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Expected O, but got Unknown //IL_019d: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Expected O, but got Unknown //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_01b1: Expected O, but got Unknown //IL_01be: Unknown result type (might be due to invalid IL or missing references) //IL_01c4: Expected O, but got Unknown //IL_01e1: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Expected O, but got Unknown //IL_01f4: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: Expected O, but got Unknown return new CodeMatcher(instructions, (ILGenerator)null).MatchEndForward((CodeMatch[])(object)new CodeMatch[3] { new CodeMatch((OpCode?)OpCodes.Ldarg_0, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Call, (object)AccessTools.Method(typeof(Smelter), "GetFuel", (Type[])null, (Type[])null), (string)null), new CodeMatch((OpCode?)OpCodes.Stloc_3, (object)null, (string)null) }).Advance(1).Insert((CodeInstruction[])(object)new CodeInstruction[7] { new CodeInstruction(OpCodes.Ldarg_0, (object)null), new CodeInstruction(OpCodes.Ldarg_0, (object)null), new CodeInstruction(OpCodes.Ldfld, (object)AccessTools.Field(typeof(Smelter), "m_nview")), new CodeInstruction(OpCodes.Ldloc_1, (object)null), new CodeInstruction(OpCodes.Ldloc_3, (object)null), new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(SmelterProcess), "QuickRefuel", (Type[])null, (Type[])null)), new CodeInstruction(OpCodes.Stloc_3, (object)null) }) .MatchEndForward((CodeMatch[])(object)new CodeMatch[3] { new CodeMatch((OpCode?)OpCodes.Ldarg_0, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Call, (object)AccessTools.Method(typeof(Smelter), "GetQueuedOre", (Type[])null, (Type[])null), (string)null), new CodeMatch((OpCode?)OpCodes.Stloc_S, (object)null, (string)null) }) .Advance(1) .Insert((CodeInstruction[])(object)new CodeInstruction[7] { new CodeInstruction(OpCodes.Ldarg_0, (object)null), new CodeInstruction(OpCodes.Ldarg_0, (object)null), new CodeInstruction(OpCodes.Ldfld, (object)AccessTools.Field(typeof(Smelter), "m_nview")), new CodeInstruction(OpCodes.Ldloc_1, (object)null), new CodeInstruction(OpCodes.Ldloc_S, (object)4), new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(SmelterProcess), "QuickCraft", (Type[])null, (Type[])null)), new CodeInstruction(OpCodes.Stloc_S, (object)4) }) .InstructionEnumeration(); } [HarmonyPostfix] [HarmonyPatch(typeof(Smelter), "UpdateSmelter")] private static void Smelter_UpdateSmelter_Postfix(Smelter __instance, ZNetView ___m_nview) { SmelterProcess.Craft(__instance, ___m_nview); SmelterProcess.Refuel(__instance, ___m_nview); } [HarmonyPrefix] [HarmonyPatch(typeof(Smelter), "Spawn")] private static bool Smelter_Spawn_Prefix(Smelter __instance, string ore, int stack) { return !SmelterProcess.Store(__instance, ore, stack); } [HarmonyPrefix] [HarmonyPatch(typeof(SapCollector), "IncreseLevel")] private static bool SapCollector_IncreseLevel_Prefix(SapCollector __instance, ZNetView ___m_nview, int i) { return !SapCollectorProcess.Store(__instance, ___m_nview, i); } [HarmonyTranspiler] [HarmonyPatch(typeof(WispSpawner), "TrySpawn")] public static IEnumerable WispSpawner_TrySpawn_Transpiler(IEnumerable instructions, ILGenerator generator) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Expected O, but got Unknown //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Expected O, but got Unknown //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Expected O, but got Unknown //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Expected O, but got Unknown //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Expected O, but got Unknown //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Expected O, but got Unknown //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Expected O, but got Unknown Label label = default(Label); return new CodeMatcher(instructions, generator).MatchEndForward((CodeMatch[])(object)new CodeMatch[2] { new CodeMatch((OpCode?)OpCodes.Ldarg_0, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Ldfld, (object)AccessTools.Field(typeof(WispSpawner), "m_spawnPoint"), (string)null) }).Insert((CodeInstruction[])(object)new CodeInstruction[1] { new CodeInstruction(OpCodes.Ldarg_0, (object)null) }).CreateLabel(ref label) .Insert((CodeInstruction[])(object)new CodeInstruction[5] { new CodeInstruction(OpCodes.Ldarg_0, (object)null), new CodeInstruction(OpCodes.Ldfld, (object)AccessTools.Field(typeof(WispSpawner), "m_nview")), new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(WispSpawnerProcess), "Store", (Type[])null, (Type[])null)), new CodeInstruction(OpCodes.Brfalse_S, (object)label), new CodeInstruction(OpCodes.Ret, (object)null) }) .Instructions(); } [HarmonyPostfix] [HarmonyPatch(typeof(Turret), "UpdateAttack")] private static void Turret_UpdateAttack_Postfix(Turret __instance, ZNetView ___m_nview, float dt) { TurretProcess.Charge(__instance, ___m_nview, dt); } [HarmonyPostfix] [HarmonyPatch(typeof(Turret), "OnDestroyed")] private static void Turret_OnDestroyed_Postfix(Turret __instance) { TurretProcess.ClearTimer(__instance); } } internal class Processor { public static readonly Processor Beehive; public static readonly Processor Bonfire; public static readonly Processor BlastFurnace; public static readonly Processor Campfire; public static readonly Processor CharcoalKiln; public static readonly Processor CookingStation; public static readonly Processor Fermenter; public static readonly Processor HangingBrazier; public static readonly Processor Hearth; public static readonly Processor IronCookingStation; public static readonly Processor JackOTurnip; public static readonly Processor Sconce; public static readonly Processor Smelter; public static readonly Processor SpinningWheel; public static readonly Processor StandingBlueBurningIronTorch; public static readonly Processor StandingBrazier; public static readonly Processor StandingGreenBurningIronTorch; public static readonly Processor StandingIronTorch; public static readonly Processor StandingWoodTorch; public static readonly Processor StoneOven; public static readonly Processor Windmill; public static readonly Processor WispFountain; public static readonly Processor SapExtractor; public static readonly Processor EitrRefinery; public static readonly Processor Ballista; private static readonly List AllInstance; public readonly string name; public readonly Process defaultAllowedProcesses; public readonly IEnumerable processes; static Processor() { Beehive = new Processor("$piece_beehive", Process.Store, Process.None, Process.Store); Bonfire = new Processor("$piece_bonfire", Process.Refuel, Process.None, Process.Refuel); BlastFurnace = new Processor("$piece_blastfurnace", Process.Craft | Process.Refuel | Process.Store, Process.None, Process.Craft, Process.Refuel, Process.Store); Campfire = new Processor("$piece_firepit", Process.Refuel, Process.None, Process.Refuel); CharcoalKiln = new Processor("$piece_charcoalkiln", Process.Craft | Process.Store, Process.None, Process.Craft, Process.Store); CookingStation = new Processor("$piece_cookingstation", Process.Store, Process.None, Process.Craft, Process.Store); Fermenter = new Processor("$piece_fermenter", Process.Craft | Process.Store, Process.None, Process.Craft, Process.Store); HangingBrazier = new Processor("$piece_brazierceiling01", Process.Refuel, Process.None, Process.Refuel); Hearth = new Processor("$piece_hearth", Process.Refuel, Process.None, Process.Refuel); IronCookingStation = new Processor("$piece_cookingstation_iron", Process.Store, Process.None, Process.Craft, Process.Store); JackOTurnip = new Processor("$piece_jackoturnip", Process.Refuel, Process.None, Process.Refuel); Sconce = new Processor("$piece_sconce", Process.Refuel, Process.None, Process.Refuel); Smelter = new Processor("$piece_smelter", Process.Craft | Process.Refuel | Process.Store, Process.None, Process.Craft, Process.Refuel, Process.Store); SpinningWheel = new Processor("$piece_spinningwheel", Process.Store, Process.None, Process.Craft, Process.Store); StandingBlueBurningIronTorch = new Processor("$piece_groundtorchblue", Process.Refuel, Process.None, Process.Refuel); StandingBrazier = new Processor("$piece_brazierfloor01", Process.Refuel, Process.None, Process.Refuel); StandingGreenBurningIronTorch = new Processor("$piece_groundtorchgreen", Process.Refuel, Process.None, Process.Refuel); StandingIronTorch = new Processor("$piece_groundtorch", Process.Refuel, Process.None, Process.Refuel); StandingWoodTorch = new Processor("$piece_groundtorchwood", Process.Refuel, Process.None, Process.Refuel); StoneOven = new Processor("$piece_oven", Process.Craft | Process.Refuel | Process.Store, Process.None, Process.Craft, Process.Refuel, Process.Store); Windmill = new Processor("$piece_windmill", Process.Store, Process.None, Process.Craft, Process.Store); WispFountain = new Processor("$piece_wisplure", Process.Store, Process.None, Process.Store); SapExtractor = new Processor("$piece_sapcollector", Process.Store, Process.None, Process.Store); EitrRefinery = new Processor("$piece_eitrrefinery", Process.Store, Process.None, Process.Craft, Process.Refuel, Process.Store); Ballista = new Processor("$piece_turret", Process.Charge, Process.None, Process.Charge); AllInstance = new List { Beehive, Bonfire, BlastFurnace, Campfire, CharcoalKiln, CookingStation, Fermenter, HangingBrazier, Hearth, IronCookingStation, JackOTurnip, Sconce, Smelter, SpinningWheel, StandingBlueBurningIronTorch, StandingBrazier, StandingGreenBurningIronTorch, StandingIronTorch, StandingWoodTorch, StoneOven, Windmill, WispFountain, SapExtractor, EitrRefinery, Ballista }; } public static IEnumerable GetAllInstance() { return AllInstance.ToList(); } private Processor(string name, Process defaultAllowedProcesses, params Process[] processes) { this.name = name; this.processes = new List(processes); this.defaultAllowedProcesses = defaultAllowedProcesses; } } [Flags] internal enum Process : long { None = 0L, [LocalizedDescription("automatics", "@config_automatic_processing_processing_type_craft")] Craft = 1L, [LocalizedDescription("automatics", "@config_automatic_processing_processing_type_refuel")] Refuel = 2L, [LocalizedDescription("automatics", "@config_automatic_processing_processing_type_store")] Store = 4L, [LocalizedDescription("automatics", "@config_automatic_processing_processing_type_charge")] Charge = 8L, [LocalizedDescription("automatics", "@select_all")] All = 0xFL } internal static class SapCollectorProcess { public static bool Store(SapCollector sapCollector, ZNetView zNetView, int increaseCount) { //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007b: 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_014b: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) if (!Config.EnableAutomaticProcessing) { return false; } if (!Objects.HasValidOwnership(zNetView)) { return false; } string name = sapCollector.m_name; if (!Logics.IsAllowProcessing(name, Process.Store)) { return false; } int num = zNetView.GetZDO().GetInt("level", 0) + increaseCount; if (num <= 0) { return false; } ItemDrop spawnItem = sapCollector.m_spawnItem; SharedData shared = spawnItem.m_itemData.m_shared; string name2 = shared.m_name; int worldLevel = spawnItem.m_itemData.m_worldLevel; int num2 = Config.ProductStacksOfSuppressProcessing(name); Vector3 position = ((Component)sapCollector).transform.position; int num3 = num; foreach (var nearbyContainer in Logics.GetNearbyContainers(name, position)) { Container item = nearbyContainer.container; if (num3 <= 0) { break; } Inventory inventory = item.GetInventory(); int num4 = inventory.CountItems(name2, -1, true); int num5 = num3; int num6 = num4 / shared.m_maxStackSize; if (num2 > 0) { if (num6 >= num2) { continue; } int num7 = inventory.FindFreeStackSpace(name2, (float)worldLevel); if (num7 == 0) { continue; } num5 = Mathf.Min(num5, num7); } if ((!Config.StoreOnlyIfProductExists(name) || Inventories.HaveItem(inventory, name2, 0f, WorldLevelMatchMode.Ignore, 1)) && inventory.AddItem(((Component)spawnItem).gameObject, num5)) { int num8 = inventory.CountItems(name2, -1, true) - num4; Logics.StoreLog(name2, num8, item.m_name, ((Component)item).transform.position, name, position); num3 -= num8; } } zNetView.GetZDO().Set("level", Mathf.Clamp(num3, 0, sapCollector.m_maxLevel)); return true; } } internal static class SmelterProcess { private static readonly HashSet SkipQuickCraft; private static readonly HashSet FirstQuickCraft; private static readonly HashSet SkipQuickRefuel; private static readonly HashSet FirstQuickRefuel; private static float _lastQuickCraftReset; private static float _lastQuickRefuelReset; static SmelterProcess() { SkipQuickCraft = new HashSet(); FirstQuickCraft = new HashSet(); SkipQuickRefuel = new HashSet(); FirstQuickRefuel = new HashSet(); } private static ItemConversion GetItemConversion(Smelter smelter, string queuedOre) { return ((IEnumerable)smelter.m_conversion).FirstOrDefault((Func)((ItemConversion x) => ((Object)((Component)x.m_from).gameObject).name == queuedOre)); } public static void Cleanup() { SkipQuickCraft.Clear(); FirstQuickCraft.Clear(); SkipQuickRefuel.Clear(); FirstQuickRefuel.Clear(); } [UsedImplicitly] public static string QuickCraft(Smelter smelter, ZNetView zNetView, float loopCount, string ore) { //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: 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_027d: Unknown result type (might be due to invalid IL or missing references) //IL_026f: 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_028f: Unknown result type (might be due to invalid IL or missing references) //IL_0231: Unknown result type (might be due to invalid IL or missing references) //IL_0237: Unknown result type (might be due to invalid IL or missing references) if (loopCount < 1f) { return ore; } if (!string.IsNullOrEmpty(ore)) { return ore; } if (!Config.EnableAutomaticProcessing) { return ore; } if (!Objects.HasValidOwnership(zNetView)) { return ore; } if (Time.time - _lastQuickCraftReset > 1f) { _lastQuickCraftReset = Time.time; SkipQuickCraft.Clear(); FirstQuickCraft.Clear(); } ZDOID uid = zNetView.GetZDO().m_uid; if (SkipQuickCraft.Contains(uid)) { return ore; } string name = smelter.m_name; if (!Logics.IsAllowProcessing(name, Process.Craft)) { return ore; } int num = Config.MaterialCountOfSuppressProcessing(name); int num2 = Config.ProductStacksOfSuppressProcessing(name); Transform transform = ((Component)smelter).transform; Vector3 position = transform.position; List<(Container, Inventory)> list = (from x in Logics.GetNearbyContainers(name, position) select (x.container, x.container.GetInventory())).ToList(); bool flag = false; foreach (ItemConversion item2 in smelter.m_conversion) { Container val = null; bool flag2 = false; SharedData shared = item2.m_from.m_itemData.m_shared; ItemData itemData = item2.m_to.m_itemData; SharedData shared2 = itemData.m_shared; foreach (var (val2, val3) in list) { if (Object.op_Implicit((Object)(object)val) && flag2) { break; } if ((Object)(object)val == (Object)null && Inventories.HaveItem(val3, shared.m_name, 0f, WorldLevelMatchMode.Ignore, num + 1)) { val = val2; } if (num2 > 0 && !flag2 && val3.CountItems(shared2.m_name, -1, true) / shared2.m_maxStackSize < num2) { flag2 = val3.CanAddItem(itemData, 1); } } if (Object.op_Implicit((Object)(object)val) && (num2 == 0 || flag2)) { ItemData item = val.GetInventory().GetItem(shared.m_name, -1, false); val.GetInventory().RemoveOneItem(item); Reflections.InvokeMethod(smelter, "QueueOre", ((Object)item.m_dropPrefab).name); Logics.CraftingLog(shared.m_name, 1, val.m_name, ((Component)val).transform.position, name, position, shared2.m_name); flag = true; break; } } if (!flag) { SkipQuickCraft.Add(uid); return ore; } if (FirstQuickCraft.Add(uid)) { smelter.m_oreAddedEffects.Create(position, transform.rotation, (Transform)null, 1f, -1); } return zNetView.GetZDO().GetString("item0", ""); } [UsedImplicitly] public static void Craft(Smelter smelter, ZNetView zNetView) { //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_02e8: Unknown result type (might be due to invalid IL or missing references) //IL_02ee: Unknown result type (might be due to invalid IL or missing references) if (!Config.EnableAutomaticProcessing || !Objects.HasValidOwnership(zNetView)) { return; } string name = smelter.m_name; if (!Logics.IsAllowProcessing(name, Process.Craft)) { return; } int @int = zNetView.GetZDO().GetInt("queued", 0); if (@int >= smelter.m_maxOre || (Config.SupplyOnlyWhenMaterialsRunOut(name) && @int > 0)) { return; } Dictionary dictionary = new Dictionary(); List conversions = new List(); for (int i = 0; i < @int; i++) { string @string = zNetView.GetZDO().GetString("item" + i, ""); if (!string.IsNullOrEmpty(@string)) { ItemConversion itemConversion = GetItemConversion(smelter, @string); if (itemConversion != null) { conversions.Add(itemConversion); string name2 = itemConversion.m_to.m_itemData.m_shared.m_name; dictionary[name2] = ((!dictionary.TryGetValue(name2, out var value)) ? 1 : (value + 1)); } } } conversions.Reverse(); conversions.AddRange(smelter.m_conversion.Where((ItemConversion x) => !conversions.Contains(x))); int num = Config.MaterialCountOfSuppressProcessing(name); int num2 = Config.ProductStacksOfSuppressProcessing(name); Vector3 position = ((Component)smelter).transform.position; List<(Container, Inventory)> list = (from x in Logics.GetNearbyContainers(name, position) select (x.container, x.container.GetInventory())).ToList(); foreach (ItemConversion item2 in conversions) { Container val = null; bool flag = false; SharedData shared = item2.m_from.m_itemData.m_shared; ItemData itemData = item2.m_to.m_itemData; SharedData shared2 = itemData.m_shared; foreach (var (val2, val3) in list) { if (Object.op_Implicit((Object)(object)val) && flag) { break; } if ((Object)(object)val == (Object)null && Inventories.HaveItem(val3, shared.m_name, 0f, WorldLevelMatchMode.Ignore, num + 1)) { val = val2; } if (num2 > 0 && !flag) { if (!dictionary.TryGetValue(shared2.m_name, out var value2)) { value2 = 0; } if ((val3.CountItems(shared2.m_name, -1, true) + value2) / shared2.m_maxStackSize < num2) { flag = val3.CanAddItem(itemData, 1); } } } if (Object.op_Implicit((Object)(object)val) && (num2 == 0 || flag)) { ItemData item = val.GetInventory().GetItem(shared.m_name, -1, false); val.GetInventory().RemoveOneItem(item); zNetView.InvokeRPC("RPC_AddOre", new object[1] { ((Object)item.m_dropPrefab).name }); Logics.CraftingLog(shared.m_name, 1, val.m_name, ((Component)val).transform.position, name, position, shared2.m_name); break; } } } [UsedImplicitly] public static float QuickRefuel(Smelter smelter, ZNetView zNetView, float loopCount, float fuel) { //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0068: 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_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: 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_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0198: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: 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) if (loopCount < 1f) { return fuel; } if (fuel > 0f) { return fuel; } if (!Config.EnableAutomaticProcessing) { return fuel; } if (!Objects.HasValidOwnership(zNetView)) { return fuel; } if (Time.time - _lastQuickRefuelReset > 1f) { _lastQuickRefuelReset = Time.time; SkipQuickRefuel.Clear(); FirstQuickRefuel.Clear(); } ZDOID uid = zNetView.GetZDO().m_uid; if (SkipQuickRefuel.Contains(uid)) { return fuel; } string name = smelter.m_name; if (!Logics.IsAllowProcessing(name, Process.Refuel)) { return fuel; } if (Config.RefuelOnlyWhenMaterialsSupplied(name) && zNetView.GetZDO().GetInt("queued", 0) == 0) { return fuel; } int num = Config.FuelCountOfSuppressProcessing(name); Transform transform = ((Component)smelter).transform; Vector3 position = transform.position; string name2 = smelter.m_fuelItem.m_itemData.m_shared.m_name; bool flag = false; foreach (var nearbyContainer in Logics.GetNearbyContainers(name, position)) { Container item = nearbyContainer.container; if (Inventories.HaveItem(item.GetInventory(), name2, 0f, WorldLevelMatchMode.Ignore, num + 1)) { item.GetInventory().RemoveItem(name2, 1, -1, true); zNetView.InvokeRPC("RPC_AddFuel", Array.Empty()); Logics.RefuelLog(name2, 1, name, position, item.m_name, ((Component)item).transform.position); flag = true; break; } } if (!flag) { SkipQuickRefuel.Add(uid); return fuel; } fuel += 1f; zNetView.GetZDO().Set("fuel", fuel); if (FirstQuickRefuel.Add(uid)) { smelter.m_fuelAddedEffects.Create(position, transform.rotation, transform, 1f, -1); } return fuel; } [UsedImplicitly] public static void Refuel(Smelter smelter, ZNetView zNetView) { //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_009e: 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_010a: Unknown result type (might be due to invalid IL or missing references) if (!Config.EnableAutomaticProcessing || !Objects.HasValidOwnership(zNetView)) { return; } string name = smelter.m_name; if (!Logics.IsAllowProcessing(name, Process.Refuel)) { return; } float @float = zNetView.GetZDO().GetFloat("fuel", 0f); if (@float >= (float)(smelter.m_maxFuel - 1) || (Config.RefuelOnlyWhenOutOfFuel(name) && @float > 0f) || (Config.RefuelOnlyWhenMaterialsSupplied(name) && zNetView.GetZDO().GetInt("queued", 0) == 0)) { return; } int num = Config.FuelCountOfSuppressProcessing(name); Vector3 position = ((Component)smelter).transform.position; string name2 = smelter.m_fuelItem.m_itemData.m_shared.m_name; foreach (var nearbyContainer in Logics.GetNearbyContainers(name, position)) { Container item = nearbyContainer.container; if (Inventories.HaveItem(item.GetInventory(), name2, 0f, WorldLevelMatchMode.Ignore, num + 1)) { item.GetInventory().RemoveItem(name2, 1, -1, true); zNetView.InvokeRPC("RPC_AddFuel", Array.Empty()); Logics.RefuelLog(name2, 1, name, position, item.m_name, ((Component)item).transform.position); break; } } } public static bool Store(Smelter smelter, string ore, int stack) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0060: 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_0130: 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_0158: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Unknown result type (might be due to invalid IL or missing references) if (!Config.EnableAutomaticProcessing) { return false; } if (!Objects.HasValidOwnership((Component)(object)smelter, out var _)) { return false; } string name = smelter.m_name; if (!Logics.IsAllowProcessing(name, Process.Store)) { return false; } ItemConversion itemConversion = GetItemConversion(smelter, ore); if (itemConversion == null) { return false; } Vector3 position = ((Component)smelter).transform.position; ItemDrop to = itemConversion.m_to; string name2 = to.m_itemData.m_shared.m_name; int num = stack; foreach (var nearbyContainer in Logics.GetNearbyContainers(name, position)) { Container item = nearbyContainer.container; if (num <= 0) { break; } Inventory inventory = item.GetInventory(); int num2 = inventory.CountItems(name2, -1, true); if ((!Config.StoreOnlyIfProductExists(name) || Inventories.HaveItem(inventory, name2, 0f, WorldLevelMatchMode.Ignore, 1)) && inventory.AddItem(((Component)to).gameObject, stack)) { int num3 = inventory.CountItems(name2, -1, true) - num2; Logics.StoreLog(name2, num3, item.m_name, ((Component)item).transform.position, name, position); num -= num3; } } if (num == stack) { return false; } smelter.m_produceEffects.Create(position, ((Component)smelter).transform.rotation, (Transform)null, 1f, -1); if (num > 0) { Object.Instantiate(((Component)itemConversion.m_to).gameObject, smelter.m_outputPoint.position, smelter.m_outputPoint.rotation).GetComponent().m_itemData.m_stack = num; } return true; } } internal static class TurretProcess { private static readonly Dictionary ChargeTimers; static TurretProcess() { ChargeTimers = new Dictionary(); } private static ItemData FindAmmoItem(Turret turret, Inventory inventory, bool onlyCurrentlyLoadableType) { return Reflections.InvokeMethod(turret, "FindAmmoItem", new object[2] { inventory, onlyCurrentlyLoadableType }); } private static bool CanCharge(Turret turret, float delta) { int instanceID = ((Object)turret).GetInstanceID(); if (!ChargeTimers.TryGetValue(instanceID, out var value)) { ChargeTimers.Add(instanceID, 0f); value = 0f; } value += delta; if (value < 1f) { ChargeTimers[instanceID] = value; return false; } ChargeTimers[instanceID] = 0f; return true; } public static void Charge(Turret turret, ZNetView zNetView, float delta) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0150: 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) if (!Config.EnableAutomaticProcessing || !Objects.HasValidOwnership(zNetView)) { return; } string name = turret.m_name; if (!Logics.IsAllowProcessing(name, Process.Charge) || !CanCharge(turret, delta) || turret.GetAmmo() >= turret.m_maxAmmo) { return; } int num = Config.NumberOfItemsToStopCharge(name); Vector3 position = ((Component)turret).transform.position; foreach (var nearbyContainer in Logics.GetNearbyContainers(name, position)) { Container item = nearbyContainer.container; Inventory inventory = item.GetInventory(); ItemData val = FindAmmoItem(turret, inventory, onlyCurrentlyLoadableType: true); if (val == null && turret.GetAmmo() == 0) { foreach (string item2 in turret.m_allowedAmmo.Select((AmmoType type) => type.m_ammo.m_itemData.m_shared.m_name)) { val = inventory.GetAmmoItem(item2, (string)null); if (val != null) { break; } } } if (val != null && Inventories.HaveItem(inventory, val.m_shared.m_name, 0f, WorldLevelMatchMode.Ignore, num + 1)) { inventory.RemoveItem(val, 1); zNetView.InvokeRPC("RPC_AddAmmo", new object[1] { ((Object)val.m_dropPrefab).name }); Logics.ChargeLog(val.m_shared.m_name, 1, name, position, item.m_name, ((Component)item).transform.position); break; } } } public static void ClearTimer(Turret turret) { ChargeTimers.Remove(((Object)turret).GetInstanceID()); } } internal static class WispSpawnerProcess { [UsedImplicitly] public static bool Store(WispSpawner wispSpawner, ZNetView zNetView) { //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) if (!Config.EnableAutomaticProcessing) { return false; } if (!Objects.HasValidOwnership(zNetView)) { return false; } string name = wispSpawner.m_name; if (!Logics.IsAllowProcessing(name, Process.Store)) { return false; } Pickable component = wispSpawner.m_wispPrefab.GetComponent(); if (!Object.op_Implicit((Object)(object)component)) { return false; } ItemDrop component2 = component.m_itemPrefab.GetComponent(); if (!Object.op_Implicit((Object)(object)component2)) { return false; } SharedData shared = component2.m_itemData.m_shared; string name2 = shared.m_name; int worldLevel = component2.m_itemData.m_worldLevel; int num = Config.ProductStacksOfSuppressProcessing(name); Vector3 position = ((Component)wispSpawner).transform.position; foreach (var nearbyContainer in Logics.GetNearbyContainers(name, position)) { Container item = nearbyContainer.container; Inventory inventory = item.GetInventory(); int num2 = inventory.CountItems(name2, -1, true) / shared.m_maxStackSize; if ((num <= 0 || (num2 < num && inventory.FindFreeStackSpace(name2, (float)worldLevel) != 0)) && (!Config.StoreOnlyIfProductExists(name) || Inventories.HaveItem(inventory, name2, 0f, WorldLevelMatchMode.Ignore, 1)) && inventory.AddItem(((Component)component2).gameObject, 1)) { zNetView.GetZDO().Set("LastSpawn", ZNet.instance.GetTime().Ticks); Logics.StoreLog(name2, 1, item.m_name, ((Component)item).transform.position, name, position); return true; } } return false; } } } namespace Automatics.AutomaticPickup { [DisallowMultipleComponent] internal sealed class AutomaticPickup : MonoBehaviour { private Player _player; private float _pickupTimer; private bool _active; private void Awake() { _player = ((Component)this).GetComponent(); if (((Character)_player).IsOwner()) { ((MonoBehaviour)this).StartCoroutine("Pickup"); } } private void OnDestroy() { if (((Character)_player).IsOwner()) { ((MonoBehaviour)this).StopCoroutine("Pickup"); } _player = null; } private IEnumerator Pickup() { while (true) { if (!_active) { yield return (object)new WaitForSeconds(0.1f); continue; } _active = false; KeyboardShortcut pickupAllNearbyKey = Config.PickupAllNearbyKey; if ((int)((KeyboardShortcut)(ref pickupAllNearbyKey)).MainKey == 0) { PickupAllNearby(_player, (Pickable x) => true); yield return null; PickupAllNearby(_player, (PickableItem x) => true); yield return null; PickupAllNearby(_player, (ItemDrop x) => x.m_autoPickup); continue; } GameObject hovering = Reflections.GetField(_player, "m_hovering"); if (!Object.op_Implicit((Object)(object)hovering)) { continue; } float field = Reflections.GetField(_player, "m_lastHoverInteractTime"); if ((double)(Time.time - field) < 0.20000000298023224) { continue; } Reflections.SetField(_player, "m_lastHoverInteractTime", Time.time); Pickable componentInParent = hovering.GetComponentInParent(); if (Object.op_Implicit((Object)(object)componentInParent)) { string pickableName = GetPickableName(componentInParent); PickupAllNearby(_player, (Pickable x) => GetPickableName(x) == pickableName); Reflections.InvokeMethod(_player, "DoInteractAnimation", hovering.transform.position); continue; } yield return null; PickableItem componentInParent2 = hovering.GetComponentInParent(); if (Object.op_Implicit((Object)(object)componentInParent2)) { string itemName2 = GetPickableItemName(componentInParent2); PickupAllNearby(_player, (PickableItem x) => GetPickableItemName(x) == itemName2); Reflections.InvokeMethod(_player, "DoInteractAnimation", hovering.transform.position); continue; } yield return null; ItemDrop componentInParent3 = hovering.GetComponentInParent(); if (Object.op_Implicit((Object)(object)componentInParent3)) { string itemName = GetItemDropName(componentInParent3); PickupAllNearby(_player, (ItemDrop x) => GetItemDropName(x) == itemName); Reflections.InvokeMethod(_player, "DoInteractAnimation", hovering.transform.position); } } } private void Update() { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) if (Game.IsPaused()) { return; } KeyboardShortcut pickupAllNearbyKey = Config.PickupAllNearbyKey; if ((int)((KeyboardShortcut)(ref pickupAllNearbyKey)).MainKey != 0 && !((Character)_player).InAttack() && !((Character)_player).InDodge() && Reflections.InvokeMethod(_player, "TakeInput")) { pickupAllNearbyKey = Config.PickupAllNearbyKey; if (((KeyboardShortcut)(ref pickupAllNearbyKey)).IsDown()) { _active = true; } } } private void FixedUpdate() { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) if (Game.IsPaused()) { return; } KeyboardShortcut pickupAllNearbyKey = Config.PickupAllNearbyKey; if ((int)((KeyboardShortcut)(ref pickupAllNearbyKey)).MainKey == 0 && !(Config.AutomaticPickupInterval <= 0f)) { _pickupTimer += Time.deltaTime; if (!(_pickupTimer < Config.AutomaticPickupInterval)) { _pickupTimer = 0f; _active = true; } } } private static string GetPickableName(Pickable pickable) { return pickable.GetHoverName(); } private static string GetPickableItemName(PickableItem pickableItem) { if (Object.op_Implicit((Object)(object)pickableItem.m_itemPrefab)) { return pickableItem.m_itemPrefab.m_itemData.m_shared.m_name; } return ""; } private static string GetItemDropName(ItemDrop itemDrop) { return itemDrop.m_itemData.m_shared.m_name; } private static void PickupAllNearby(Player player, Predicate predicate) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) Vector3 position = ((Component)player).transform.position; float automaticPickupRange = Config.AutomaticPickupRange; foreach (PickableItem item in InstanceCache.GetAllInstance()) { if (!(Vector3.Distance(position, ((Component)item).transform.position) > automaticPickupRange) && predicate(item) && Objects.GetZNetView((Component)(object)item, out var zNetView) && zNetView.IsValid()) { PickPickableItem(player, item, zNetView); } } } private static void PickupAllNearby(Player player, Predicate predicate) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) Vector3 position = ((Component)player).transform.position; float automaticPickupRange = Config.AutomaticPickupRange; foreach (Pickable item in InstanceCache.GetAllInstance()) { if (Vector3.Distance(position, ((Component)item).transform.position) > automaticPickupRange || !predicate(item)) { continue; } if (item.m_tarPreventsPicking) { Floating val = Reflections.GetField(item, "m_floating"); if (!Object.op_Implicit((Object)(object)val)) { val = ((Component)item).GetComponent(); if (Object.op_Implicit((Object)(object)val)) { Reflections.SetField(item, "m_floating", val); } } if (Object.op_Implicit((Object)(object)val) && val.IsInTar()) { continue; } } if (Objects.GetZNetView((Component)(object)item, out var zNetView) && zNetView.IsValid()) { PickPickable(player, item, zNetView); } } } private static void PickupAllNearby(Player player, Predicate predicate) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) Vector3 position = ((Component)player).transform.position; float automaticPickupRange = Config.AutomaticPickupRange; foreach (ItemDrop item in GetAllItemDrop()) { if (Object.op_Implicit((Object)(object)item) && !item.IsPiece() && !(Vector3.Distance(position, ((Component)item).transform.position) > automaticPickupRange) && predicate(item) && !item.InTar() && Objects.GetZNetView((Component)(object)item, out var zNetView) && zNetView.GetZDO() != null) { PickItemDrop(player, item); } } } private static void PickPickable(Player player, Pickable pickable, ZNetView zNetView) { //IL_00f4: Unknown result type (might be due to invalid IL or missing references) if (Reflections.GetField(pickable, "m_picked") || !CanAddItem(player, pickable.m_itemPrefab, pickable.m_amount)) { return; } Inventory inventory = ((Humanoid)player).GetInventory(); inventory.AddItem(pickable.m_itemPrefab, pickable.m_amount); if (!pickable.m_extraDrops.IsEmpty()) { int num = 0; foreach (ItemData dropListItem in pickable.m_extraDrops.GetDropListItems()) { if (CanAddItem(player, dropListItem.m_dropPrefab, dropListItem.m_stack)) { inventory.AddItem(dropListItem.m_dropPrefab, dropListItem.m_stack); continue; } Reflections.InvokeMethod(pickable, "Drop", dropListItem.m_dropPrefab, num++, dropListItem.m_stack); } } if (pickable.m_aggravateRange > 0f) { BaseAI.AggravateAllInArea(((Component)pickable).transform.position, pickable.m_aggravateRange, (AggravatedReason)2); } zNetView.InvokeRPC(ZNetView.Everybody, "RPC_SetPicked", new object[1] { true }); } private static void PickPickableItem(Player player, PickableItem pickableItem, ZNetView zNetView) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) if (!Reflections.GetField(pickableItem, "m_picked")) { int num = Reflections.InvokeMethod(pickableItem, "GetStackSize"); if (num > 0 && CanAddItem(player, pickableItem.m_itemPrefab.m_itemData, num)) { pickableItem.m_pickEffector.Create(((Component)pickableItem).transform.position, Quaternion.identity, (Transform)null, 1f, -1); ((Humanoid)player).GetInventory().AddItem(((Component)pickableItem.m_itemPrefab).gameObject, num); Reflections.SetField(pickableItem, "m_picked", value: true); zNetView.ClaimOwnership(); zNetView.Destroy(); } } } private static void PickItemDrop(Player player, ItemDrop itemDrop) { if (CanAddItem(player, itemDrop.m_itemData)) { itemDrop.Pickup((Humanoid)(object)player); } } private static bool CanAddItem(Player player, ItemData itemData, int stack = -1) { Inventory inventory = ((Humanoid)player).GetInventory(); if (!inventory.CanAddItem(itemData, stack)) { return false; } return inventory.GetTotalWeight() + itemData.GetWeight(-1) < player.m_maxCarryWeight; } private static bool CanAddItem(Player player, GameObject prefab, int stack = -1) { ItemDrop component = prefab.GetComponent(); if ((Object)(object)component != (Object)null) { return CanAddItem(player, component.m_itemData, stack); } return false; } private static IEnumerable GetAllItemDrop() { IEnumerable staticField = Reflections.GetStaticField>("s_instances"); object obj = staticField; if (obj == null) { staticField = Reflections.GetStaticField>("m_instances"); obj = staticField ?? Enumerable.Empty(); } return (IEnumerable)obj; } } internal static class Config { private const string Section = "automatic_pickup"; private static ConfigEntry _module; private static ConfigEntry _automaticPickupRange; private static ConfigEntry _automaticPickupInterval; private static ConfigEntry _pickupAllNearbyKey; public static bool ModuleDisabled => _module.Value == AutomaticsModule.Disabled; public static float AutomaticPickupRange => _automaticPickupRange.Value; public static float AutomaticPickupInterval => _automaticPickupInterval.Value; public static KeyboardShortcut PickupAllNearbyKey => _pickupAllNearbyKey.Value; public static void Initialize() { //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) Configuration instance = global::Automatics.Config.Instance; instance.ChangeSection("automatic_pickup"); _module = instance.Bind("module", AutomaticsModule.Enabled, null, delegate(ConfigurationManagerAttributes x) { x.DispName = Automatics.L10N.Translate("@config_common_disable_module_name"); x.Description = Automatics.L10N.Translate("@config_common_disable_module_description"); }); if (_module.Value != AutomaticsModule.Disabled) { _automaticPickupRange = instance.Bind("automatic_pickup_range", 4f, (1f, 64f)); _automaticPickupInterval = instance.Bind("automatic_pickup_interval", 0.5f, (0f, 4f)); _pickupAllNearbyKey = instance.Bind("pickup_all_nearby_key", default(KeyboardShortcut)); } } } [DisallowMultipleComponent] internal sealed class PickableItemCache : InstanceCache { } internal static class Module { [AutomaticsInitializer(8)] private static void Initialize() { Config.Initialize(); if (!Config.ModuleDisabled) { Hooks.OnPlayerAwake = (Action)Delegate.Combine(Hooks.OnPlayerAwake, new Action(OnPlayerAwake)); Harmony.CreateAndPatchAll(typeof(Patches), Automatics.GetHarmonyId("automatic-pickup")); } } private static void OnPlayerAwake(Player player, ZNetView zNetView) { if (zNetView.GetZDO() != null) { ((Component)player).gameObject.AddComponent(); } } } [HarmonyPatch] internal static class Patches { [HarmonyPrefix] [HarmonyPatch(typeof(Player), "Interact")] private static bool Player_Interact_Prefix(GameObject go) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)go)) { return true; } if (!Object.op_Implicit((Object)(object)go.GetComponentInParent()) && !Object.op_Implicit((Object)(object)go.GetComponentInParent()) && !Object.op_Implicit((Object)(object)go.GetComponentInParent())) { return true; } KeyboardShortcut pickupAllNearbyKey = Config.PickupAllNearbyKey; return !((KeyboardShortcut)(ref pickupAllNearbyKey)).IsPressed(); } [HarmonyPostfix] [HarmonyPatch(typeof(Pickable), "GetHoverText")] private static void Pickable_GetHoverText_Postfix(Pickable __instance, ref string __result, bool ___m_picked) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0008: 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_0019: Unknown result type (might be due to invalid IL or missing references) KeyboardShortcut pickupAllNearbyKey = Config.PickupAllNearbyKey; if ((int)((KeyboardShortcut)(ref pickupAllNearbyKey)).MainKey != 0 && !___m_picked) { pickupAllNearbyKey = Config.PickupAllNearbyKey; string text = ((object)(KeyboardShortcut)(ref pickupAllNearbyKey)).ToString(); string hoverName = __instance.GetHoverName(); string text2 = Automatics.L10N.Localize("@message_automatic_pickup_pickup_all_nearby", hoverName); __result = __result + "\n[" + text + "] " + text2; } } [HarmonyPostfix] [HarmonyPatch(typeof(PickableItem), "Awake")] private static void PickableItem_Awake_Postfix(PickableItem __instance, ZNetView ___m_nview) { if (!((Object)(object)___m_nview == (Object)null) && ___m_nview.GetZDO() != null) { ((Component)__instance).gameObject.AddComponent(); } } [HarmonyPostfix] [HarmonyPatch(typeof(PickableItem), "GetHoverText")] private static void PickableItem_GetHoverText_Postfix(PickableItem __instance, ref string __result, bool ___m_picked) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0021: 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) KeyboardShortcut pickupAllNearbyKey = Config.PickupAllNearbyKey; if ((int)((KeyboardShortcut)(ref pickupAllNearbyKey)).MainKey != 0 && !___m_picked && Object.op_Implicit((Object)(object)__instance.m_itemPrefab)) { pickupAllNearbyKey = Config.PickupAllNearbyKey; string text = ((object)(KeyboardShortcut)(ref pickupAllNearbyKey)).ToString(); string name = __instance.m_itemPrefab.m_itemData.m_shared.m_name; string text2 = Automatics.L10N.Localize("@message_automatic_pickup_pickup_all_nearby", name); __result = __result + "\n[" + text + "] " + text2; } } [HarmonyPostfix] [HarmonyPatch(typeof(ItemDrop), "GetHoverText")] private static void ItemDrop_GetHoverText_Postfix(ItemDrop __instance, ref string __result) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) KeyboardShortcut pickupAllNearbyKey = Config.PickupAllNearbyKey; if ((int)((KeyboardShortcut)(ref pickupAllNearbyKey)).MainKey != 0) { pickupAllNearbyKey = Config.PickupAllNearbyKey; string text = ((object)(KeyboardShortcut)(ref pickupAllNearbyKey)).ToString(); string name = __instance.m_itemData.m_shared.m_name; string text2 = Automatics.L10N.Localize("@message_automatic_pickup_pickup_all_nearby", name); __result = __result + "\n[" + text + "] " + text2; } } } } namespace Automatics.AutomaticMining { [DisallowMultipleComponent] public class AutomaticMining : MonoBehaviour { private static readonly IList AllInstance; private static readonly RaycastHit[] RaycastHitBuffer; private static readonly Lazy MineralMaskLazy; private Component _component; private ZNetView _zNetView; private static int MineralMask => MineralMaskLazy.Value; static AutomaticMining() { AllInstance = new List(); RaycastHitBuffer = (RaycastHit[])(object)new RaycastHit[128]; MineralMaskLazy = new Lazy(() => LayerMask.GetMask(new string[4] { "piece", "Default", "static_solid", "Default_small" })); } private void Awake() { _component = GetDestructibleComponent(); if (!Object.op_Implicit((Object)(object)_component)) { throw new Exception("Component must inherit IDestructible."); } if (!Objects.GetZNetView(_component, out _zNetView)) { throw new Exception("Component does not have ZNetView"); } AllInstance.Add(this); } private void OnDestroy() { AllInstance.Remove(this); _component = null; _zNetView = null; } public static void TryMining(Player player) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) Vector3 origin = ((Component)player).transform.position; AutomaticMining automaticMining = (from x in AllInstance let distance = Vector3.Distance(origin, ((Component)x).transform.position) where x._zNetView.IsValid() && x._zNetView.IsOwner() && IsAllowMiningMinerals(x._component) orderby distance select x).FirstOrDefault(); if (Object.op_Implicit((Object)(object)automaticMining)) { automaticMining.Mining(player); } static bool IsAllowMiningMinerals(Component component) { string name = Objects.GetName(component); if (ValheimObject.Mineral.GetIdentify(name, out var identifier)) { return Config.AllowMiningMinerals.Contains(identifier); } return false; } } private Component GetDestructibleComponent() { IDestructible component = ((Component)this).GetComponent(); MineRock val = (MineRock)(object)((component is MineRock) ? component : null); if (val == null) { MineRock5 val2 = (MineRock5)(object)((component is MineRock5) ? component : null); if (val2 == null) { Destructible val3 = (Destructible)(object)((component is Destructible) ? component : null); if (val3 == null) { Component val4 = (Component)(object)((component is Component) ? component : null); if (val4 != null) { return val4; } return null; } return (Component)(object)val3; } return (Component)(object)val2; } return (Component)(object)val; } private void Mining(Player player) { ItemData pickaxe = GetPickaxe(player); if (pickaxe == null) { return; } Attack attack = pickaxe.m_shared.m_attack; float range = ((Config.MiningRange > 0) ? ((float)Config.MiningRange) : attack.m_attackRange); Component component = _component; MineRock val = (MineRock)(object)((component is MineRock) ? component : null); if (val == null) { MineRock5 val2 = (MineRock5)(object)((component is MineRock5) ? component : null); if (val2 == null) { Destructible val3 = (Destructible)(object)((component is Destructible) ? component : null); if (val3 != null && val3.m_minToolTier <= pickaxe.m_shared.m_toolTier) { Mining(player, pickaxe, range, (IDestructible)(object)val3, ((Component)val3).GetComponentInChildren()); } } else if (val2.m_minToolTier <= pickaxe.m_shared.m_toolTier) { Mining(player, pickaxe, range, (IDestructible)(object)val2, ((Component)val2).gameObject.GetComponentsInChildren()); } } else if (val.m_minToolTier <= pickaxe.m_shared.m_toolTier) { Mining(player, pickaxe, range, (IDestructible)(object)val, Reflections.GetField(val, "m_hitAreas")); } } private static void Mining(Player player, ItemData pickaxe, float range, IDestructible parent, params Collider[] colliders) { //IL_00e4: 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_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) if (colliders == null || colliders.Length == 0) { return; } List equipments = ((Humanoid)player).GetInventory().GetEquippedItems(); List<(Collider, Vector3)> list = (from collider in colliders let result = GetHitPosition(((Character)player).m_eye.position, collider, range) where result.Position != Vector3.zero && IsMineableMineral(collider, equipments) orderby result.Distance select (collider, result.Position)).Take(3).ToList(); foreach (var item in list) { var (collider2, val) = item; if (!IsValidPickaxe(player, pickaxe) || Vector3.Distance(((Character)player).m_eye.position, val) > (float)Config.MiningRange) { continue; } CreateHitEffect(pickaxe, val); parent.Damage(CreateHitData(player, pickaxe, val, collider2, list.Count)); UsePickaxe(player, pickaxe); Automatics.Logger.Debug(delegate { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) string text = "Unknown"; IDestructible obj = parent; Component val2 = (Component)(object)((obj is Component) ? obj : null); if (val2 != null) { text = Automatics.L10N.Translate(Objects.GetName(val2)); } string arg = text; Bounds bounds = collider2.bounds; return $"Mining: [name: {arg}, pos: {((Bounds)(ref bounds)).center}]"; }); } } private static bool IsValidPickaxe(Player player, ItemData pickaxe) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Invalid comparison between Unknown and I4 if ((int)pickaxe.m_shared.m_skillType != 12) { return false; } if (Config.NeedToEquipPickaxe && !((Humanoid)player).IsItemEquiped(pickaxe)) { return false; } return pickaxe.m_durability > 0f; } private static ItemData GetPickaxe(Player player) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Invalid comparison between Unknown and I4 ItemData currentWeapon = ((Humanoid)player).GetCurrentWeapon(); if (currentWeapon != null && currentWeapon.m_durability > 0f && (int)currentWeapon.m_shared.m_skillType == 12) { return currentWeapon; } if (Config.NeedToEquipPickaxe) { return null; } return (from x in ((Humanoid)player).GetInventory().GetAllItems() where x.m_durability > 0f && (int)x.m_shared.m_skillType == 12 orderby x.m_shared.m_toolTier select x).FirstOrDefault(); } private static (Vector3 Position, float Distance) GetHitPosition(Vector3 origin, Collider target, float range) { //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_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_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) Bounds bounds = target.bounds; Vector3 val = ((Bounds)(ref bounds)).center - origin; Physics.RaycastNonAlloc(origin, val, RaycastHitBuffer, range, MineralMask); using (IEnumerator enumerator = RaycastHitBuffer.Where((RaycastHit hit) => (Object)(object)((RaycastHit)(ref hit)).collider == (Object)(object)target && ((RaycastHit)(ref hit)).distance <= range).GetEnumerator()) { if (enumerator.MoveNext()) { RaycastHit current = enumerator.Current; return (((RaycastHit)(ref current)).point, ((RaycastHit)(ref current)).distance); } } return (Vector3.zero, -1f); } private static bool IsMineableMineral(Collider mineral, IEnumerable equipments) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0019: 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_0021: Unknown result type (might be due to invalid IL or missing references) Bounds bounds = mineral.bounds; float y = ((Bounds)(ref bounds)).max.y; ZoneSystem instance = ZoneSystem.instance; bounds = mineral.bounds; if (y >= instance.GetGroundHeight(((Bounds)(ref bounds)).center)) { return true; } if (!Config.AllowMiningUndergroundMinerals) { return false; } if (Config.NeedToEquipWishboneForUndergroundMinerals) { return equipments.Any((ItemData x) => x.m_shared.m_name == "$item_wishbone"); } return true; } private static void CreateHitEffect(ItemData pickaxe, Vector3 pos) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) pickaxe.m_shared.m_hitEffect.Create(pos, Quaternion.identity, (Transform)null, 1f, -1); pickaxe.m_shared.m_attack.m_hitEffect.Create(pos, Quaternion.identity, (Transform)null, 1f, -1); } private static HitData CreateHitData(Player player, ItemData pickaxe, Vector3 hit, Collider collider, int hitCount) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004e: 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_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Expected O, but got Unknown //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) SharedData shared = pickaxe.m_shared; HitData val = new HitData { m_toolTier = (short)shared.m_toolTier, m_statusEffectHash = (((Object)(object)shared.m_attackStatusEffect != (Object)null) ? shared.m_attackStatusEffect.NameHash() : 0), m_skill = shared.m_skillType, m_damage = pickaxe.GetDamage(), m_point = hit, m_hitCollider = collider }; Attack attack = shared.m_attack; float num = ((Character)player).GetRandomSkillFactor(shared.m_skillType); if (attack.m_multiHit && attack.m_lowerDamagePerHit && hitCount > 1) { num /= (float)hitCount * 0.75f; } val.SetAttacker((Character)(object)player); ((DamageTypes)(ref val.m_damage)).Modify(attack.m_damageMultiplier); ((DamageTypes)(ref val.m_damage)).Modify(num); ((DamageTypes)(ref val.m_damage)).Modify((float)(1.0 + (double)Mathf.Max(0, ((Character)player).GetLevel() - 1) * 0.5)); ((Character)player).GetSEMan().ModifyAttack(shared.m_skillType, ref val); return val; } private static void UsePickaxe(Player player, ItemData pickaxe) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) SharedData shared = pickaxe.m_shared; Attack attack = shared.m_attack; if (shared.m_useDurability) { pickaxe.m_durability -= shared.m_useDurabilityDrain; } ((Character)player).AddNoise(attack.m_attackHitNoise); ((Character)player).RaiseSkill(shared.m_skillType, 1f); } } internal static class Config { private const string Section = "automatic_mining"; private static ConfigEntry _module; private static ConfigEntry _enableAutomaticMining; private static ConfigEntry _miningInterval; private static ConfigEntry _miningRange; private static ConfigEntry _allowMiningMineral; private static ConfigEntry _needToEquipPickaxe; private static ConfigEntry _allowMiningUndergroundMinerals; private static ConfigEntry _needToEquipWishboneForUndergroundMinerals; private static ConfigEntry _miningKey; public static bool ModuleDisabled => _module.Value == AutomaticsModule.Disabled; public static bool EnableAutomaticMining => _enableAutomaticMining.Value; public static float MiningInterval => _miningInterval.Value; public static int MiningRange => _miningRange.Value; public static StringList AllowMiningMinerals => _allowMiningMineral.Value; public static bool NeedToEquipPickaxe => _needToEquipPickaxe.Value; public static bool AllowMiningUndergroundMinerals => _allowMiningUndergroundMinerals.Value; public static bool NeedToEquipWishboneForUndergroundMinerals => _needToEquipWishboneForUndergroundMinerals.Value; public static KeyboardShortcut MiningKey => _miningKey.Value; public static void Initialize() { //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) Configuration instance = global::Automatics.Config.Instance; instance.ChangeSection("automatic_mining"); _module = instance.Bind("module", AutomaticsModule.Enabled, null, delegate(ConfigurationManagerAttributes x) { x.DispName = Automatics.L10N.Translate("@config_common_disable_module_name"); x.Description = Automatics.L10N.Translate("@config_common_disable_module_description"); }); if (_module.Value != AutomaticsModule.Disabled) { _enableAutomaticMining = instance.Bind("enable_automatic_mining", defaultValue: true); _miningInterval = instance.Bind("mining_interval", 1.5f, (0.1f, 4f)); _miningRange = instance.Bind("mining_range", 3, (0, 32)); _allowMiningMineral = instance.BindValheimObjectList("allow_mining_mineral", ValheimObject.Mineral); _needToEquipPickaxe = instance.Bind("need_to_equip_pickaxe", defaultValue: true); _allowMiningUndergroundMinerals = instance.Bind("allow_mining_underground_minerals", defaultValue: true); _needToEquipWishboneForUndergroundMinerals = instance.Bind("need_to_equip_wishbone_for_mining_underground_minerals", defaultValue: true); _miningKey = instance.Bind("mining_key", default(KeyboardShortcut)); } } } internal static class Module { private static readonly Dictionary MiningTimers; static Module() { MiningTimers = new Dictionary(); } private static void Cleanup() { MiningTimers.Clear(); } [AutomaticsInitializer(6)] private static void Initialize() { Config.Initialize(); if (!Config.ModuleDisabled) { Hooks.OnPlayerAwake = (Action)Delegate.Combine(Hooks.OnPlayerAwake, (Action)delegate { Cleanup(); }); Hooks.OnPlayerUpdate = (Action)Delegate.Combine(Hooks.OnPlayerUpdate, new Action(OnPlayerUpdate)); Hooks.OnPlayerFixedUpdate = (Action)Delegate.Combine(Hooks.OnPlayerFixedUpdate, new Action(OnPlayerFixedUpdate)); Harmony.CreateAndPatchAll(typeof(Patches), Automatics.GetHarmonyId("automatic-mining")); } } private static void OnPlayerUpdate(Player player, bool takeInput) { //IL_002f: 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_0037: 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_0044: Unknown result type (might be due to invalid IL or missing references) if (!Config.EnableAutomaticMining || (Object)(object)Player.m_localPlayer != (Object)(object)player || !((Character)player).IsOwner() || !takeInput || Config.MiningInterval < 0.1f) { return; } KeyboardShortcut miningKey = Config.MiningKey; if ((int)((KeyboardShortcut)(ref miningKey)).MainKey != 0) { miningKey = Config.MiningKey; if (((KeyboardShortcut)(ref miningKey)).IsDown()) { AutomaticMining.TryMining(player); } } } private static void OnPlayerFixedUpdate(Player player, float delta) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: 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) if (!Config.EnableAutomaticMining || (Object)(object)Player.m_localPlayer != (Object)(object)player || !((Character)player).IsOwner() || Config.MiningInterval < 0.1f) { return; } KeyboardShortcut miningKey = Config.MiningKey; if ((int)((KeyboardShortcut)(ref miningKey)).MainKey == 0) { long playerID = player.GetPlayerID(); if (!MiningTimers.TryGetValue(playerID, out var value)) { value = 0f; } value += delta; if (value >= Config.MiningInterval) { MiningTimers[playerID] = 0f; AutomaticMining.TryMining(player); } else { MiningTimers[playerID] = value; } } } } [HarmonyPatch] public static class Patches { [HarmonyPostfix] [HarmonyPatch(typeof(Destructible), "Start")] private static void Destructible_Awake_Postfix(Destructible __instance, ZNetView ___m_nview) { if (Object.op_Implicit((Object)(object)___m_nview) && ___m_nview.GetZDO() != null) { ((Component)__instance).gameObject.AddComponent(); } } [HarmonyPostfix] [HarmonyPatch(typeof(MineRock), "Start")] private static void MineRock_Start_Postfix(MineRock __instance, ZNetView ___m_nview) { if (Object.op_Implicit((Object)(object)___m_nview) && ___m_nview.GetZDO() != null) { ((Component)__instance).gameObject.AddComponent(); } } [HarmonyPostfix] [HarmonyPatch(typeof(MineRock5), "Awake")] private static void MineRock5_Awake_Postfix(MineRock5 __instance, ZNetView ___m_nview) { if (Object.op_Implicit((Object)(object)___m_nview) && ___m_nview.GetZDO() != null) { ((Component)__instance).gameObject.AddComponent(); } } } } namespace Automatics.AutomaticMapping { internal static class AutomaticMapping { private const float DynamicScanInterval = 0.1f; private const float DynamicScanEpsilon = 0.0001f; private static float _dynamicScanAccumulator; private static float _lastAnimateTime; private static void RemoveCachedPins() { DynamicObjectMapping.RemoveCachedPins(); StaticObjectMapping.RemoveCachedPins(); Map.RefreshPins(); } private static bool CanRun(Player player) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) if (!Game.IsPaused() && (Object)(object)player == (Object)(object)Player.m_localPlayer && ((Character)player).IsOwner()) { return ZNetScene.instance.IsAreaReady(((Component)player).transform.position); } return false; } public static void Cleanup() { Navigation.Cleanup(); DynamicObjectMapping.Cleanup(); StaticObjectMapping.Cleanup(); MappingProfiler.Reset(); _dynamicScanAccumulator = 0f; _lastAnimateTime = 0f; } public static void DynamicMapping(Player player, float delta) { MappingProfiler.FlushIfDue(); if (!CanRun(player)) { return; } if (!Config.EnableAutomaticMapping) { RemoveCachedPins(); return; } _dynamicScanAccumulator += delta; if (!(_dynamicScanAccumulator + 0.0001f < 0.1f)) { _dynamicScanAccumulator -= 0.1f; if (_dynamicScanAccumulator < 0f) { _dynamicScanAccumulator = 0f; } else if (_dynamicScanAccumulator > 0.1f) { _dynamicScanAccumulator = 0.1f; } DynamicObjectMapping.Mapping(delta); Map.RefreshPins(); } } public static void Mapping(Player player, float delta, bool takeInput) { if (CanRun(player)) { if (!Config.EnableAutomaticMapping) { RemoveCachedPins(); } else { StaticObjectMapping.Mapping(delta, takeInput); } } } public static void OnRemovePin(PinData pinData) { PinIndex.Untrack(pinData); Navigation.OnRemovePin(pinData); DynamicObjectMapping.OnRemovePin(pinData); StaticObjectMapping.OnRemovePin(pinData); } public static void AnimatePins() { float time = Time.time; float delta = ((!(_lastAnimateTime <= 0f)) ? (time - _lastAnimateTime) : Time.deltaTime); _lastAnimateTime = time; DynamicObjectMapping.AnimatePins(delta); } [UsedImplicitly] public static bool SetSaveFlag(Vector3 pos, float radius) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) PinData closestPin = Map.GetClosestPin(pos, radius, (PinData x) => x.m_ownerID == 0L && !x.m_save); if (closestPin == null) { return false; } if (!StaticObjectMapping.SetSaveFlag(closestPin)) { return DynamicObjectMapping.SetSaveFlag(closestPin); } return true; } } internal static class DynamicObjectMapping { private enum CharacterKind { None, Animal, Monster } private sealed class CachedIdentifier { public int Version; public string BaseName; public CharacterKind Kind; public string Identifier; } private sealed class LevelPinNameCache { public int Level; public string BaseName; public string PinName; } private const float PinSmoothingTime = 0.2f; private const float PinSnapDistance = 96f; private const float PinSnapDistanceSq = 9216f; private const float PinTargetEpsilonSq = 0.01f; private const float PinVelocitySettledSq = 0.0001f; private static readonly Dictionary PinDataCache; private static readonly Dictionary PinKeyCache; private static readonly Dictionary PinTargetCache; private static readonly Dictionary PinVelocityCache; private static readonly IDictionary VehiclePinCache; private static readonly Dictionary VehiclePinTargetCache; private static readonly Dictionary VehiclePinVelocityCache; private static readonly HashSet KnownObjects; private static readonly ISet EmptyCacheKeys; private static readonly List FishBuffer; private static readonly List BirdBuffer; private static readonly List ShipBuffer; private static readonly List VehicleBuffer; private static readonly List RemoveKeyBuffer; private static readonly HashSet DirtyPins; private static readonly HashSet VehicleDirtyPins; private static readonly List DirtyDrainBuffer; private static readonly ConditionalWeakTable CharacterIdentifierCache; private static readonly ConditionalWeakTable CharacterLevelNameCache; private static int _dynamicClassifierVersion; private static bool _registrySubscriptionsBound; static DynamicObjectMapping() { CharacterIdentifierCache = new ConditionalWeakTable(); CharacterLevelNameCache = new ConditionalWeakTable(); PinDataCache = new Dictionary(); PinKeyCache = new Dictionary(); PinTargetCache = new Dictionary(); PinVelocityCache = new Dictionary(); VehiclePinCache = new Dictionary(); VehiclePinTargetCache = new Dictionary(); VehiclePinVelocityCache = new Dictionary(); KnownObjects = new HashSet(); EmptyCacheKeys = new HashSet(0); FishBuffer = new List(); BirdBuffer = new List(); ShipBuffer = new List(); VehicleBuffer = new List(); RemoveKeyBuffer = new List(); DirtyPins = new HashSet(); VehicleDirtyPins = new HashSet(); DirtyDrainBuffer = new List(); } private static void EnsureRegistrySubscriptions() { if (!_registrySubscriptionsBound) { _registrySubscriptionsBound = true; ValheimObject.RegistryChanged += OnValheimObjectRegistryChanged; } } private static void OnValheimObjectRegistryChanged(ValheimObject obj) { if (obj == ValheimObject.Animal || obj == ValheimObject.Monster) { _dynamicClassifierVersion++; } } private static bool TryResolveCharacterIdentifier(Character character, out CharacterKind kind, out string identifier) { int dynamicClassifierVersion = _dynamicClassifierVersion; string name = character.m_name; if (CharacterIdentifierCache.TryGetValue(character, out var value) && value.Version == dynamicClassifierVersion && (object)value.BaseName == name) { kind = value.Kind; identifier = value.Identifier; return kind != CharacterKind.None; } CharacterKind characterKind; string text; string identifier3; if (ValheimObject.Animal.GetIdentify(name, out var identifier2)) { characterKind = CharacterKind.Animal; text = identifier2; } else if (ValheimObject.Monster.GetIdentify(name, out identifier3)) { characterKind = CharacterKind.Monster; text = identifier3; } else { characterKind = CharacterKind.None; text = null; } if (value == null) { CharacterIdentifierCache.Add(character, new CachedIdentifier { Version = dynamicClassifierVersion, BaseName = name, Kind = characterKind, Identifier = text }); } else { value.Version = dynamicClassifierVersion; value.BaseName = name; value.Kind = characterKind; value.Identifier = text; } kind = characterKind; identifier = text; return kind != CharacterKind.None; } private static bool GetVehicle(string name, out (string Identifier, bool IsAllowed) data) { if (MappingObject.Vehicle.GetIdentify(name, out var identifier)) { data = (identifier, Config.AllowPinningVehicle.Contains(identifier)); return true; } data = ("", false); return false; } public static void Cleanup() { PinDataCache.Clear(); PinKeyCache.Clear(); PinTargetCache.Clear(); PinVelocityCache.Clear(); VehiclePinCache.Clear(); VehiclePinTargetCache.Clear(); VehiclePinVelocityCache.Clear(); KnownObjects.Clear(); DirtyPins.Clear(); VehicleDirtyPins.Clear(); } public static void OnObjectDestroy(Component component) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) if (Config.EnableAutomaticMapping && (Object.op_Implicit((Object)(object)component.GetComponent()) || Object.op_Implicit((Object)(object)component.GetComponent())) && Objects.GetZdoid(component, out var id) && VehiclePinCache.TryGetValue(id, out var value)) { VehiclePinTargetCache.Remove(id); VehiclePinVelocityCache.Remove(id); VehicleDirtyPins.Remove(id); Map.RemovePin(value); } } public static void RemoveCachedPins(ISet excludes = null) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_008c: 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_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) if (PinDataCache.Count == 0) { return; } if (excludes == null) { excludes = EmptyCacheKeys; } RemoveKeyBuffer.Clear(); foreach (ZDOID key in PinDataCache.Keys) { if (!excludes.Contains(key)) { RemoveKeyBuffer.Add(key); } } for (int i = 0; i < RemoveKeyBuffer.Count; i++) { ZDOID val = RemoveKeyBuffer[i]; if (PinDataCache.TryGetValue(val, out var value)) { PinDataCache.Remove(val); PinKeyCache.Remove(value); PinTargetCache.Remove(val); PinVelocityCache.Remove(val); DirtyPins.Remove(val); if (!value.m_save) { Map.RemovePin(value); } } } RemoveKeyBuffer.Clear(); } public static void OnRemovePin(PinData pinData) { RemovePinFromCache(pinData); } public static bool SetSaveFlag(PinData pinData) { if (!RemovePinFromCache(pinData)) { return false; } pinData.m_save = true; Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)2, Automatics.L10N.Localize("@message_automatic_mapping_pin_saved", pinData.m_name.Replace("\n", "")), 0, (Sprite)null); } return true; } public static void AnimatePins(float delta) { using (MappingProfiler.BeginScope(3)) { if (!(delta <= 0f)) { AnimateDirty(PinDataCache, PinTargetCache, PinVelocityCache, DirtyPins, delta); AnimateDirty(VehiclePinCache, VehiclePinTargetCache, VehiclePinVelocityCache, VehicleDirtyPins, delta); } } } private static void AnimateDirty(IDictionary pinCache, IDictionary targetCache, IDictionary velocityCache, HashSet dirty, float delta) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: 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_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) if (dirty.Count == 0) { return; } DirtyDrainBuffer.Clear(); foreach (ZDOID item in dirty) { DirtyDrainBuffer.Add(item); } for (int i = 0; i < DirtyDrainBuffer.Count; i++) { ZDOID val = DirtyDrainBuffer[i]; if (!pinCache.TryGetValue(val, out var value) || value == null || !targetCache.TryGetValue(val, out var value2)) { dirty.Remove(val); } else if (StepPinAnimation(velocityCache, val, value, value2, delta)) { dirty.Remove(val); } } DirtyDrainBuffer.Clear(); } private static bool StepPinAnimation(IDictionary velocityCache, ZDOID uniqueId, PinData pinData, Vector3 target, float delta) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: 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_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //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_0038: 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_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_002e: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0055: 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_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) Vector3 pos = pinData.m_pos; if (!velocityCache.TryGetValue(uniqueId, out var value)) { value = Vector3.zero; } Vector3 val = pos - target; Vector3 val2; if (((Vector3)(ref val)).sqrMagnitude >= 9216f) { val2 = target; value = Vector3.zero; } else { val2 = Vector3.SmoothDamp(pos, target, ref value, 0.2f, float.PositiveInfinity, delta); } val = val2 - target; int num; if (((Vector3)(ref val)).sqrMagnitude < 0.01f) { num = ((((Vector3)(ref value)).sqrMagnitude < 0.0001f) ? 1 : 0); if (num != 0) { val2 = target; value = Vector3.zero; } } else { num = 0; } velocityCache[uniqueId] = value; Map.MovePin(pinData, val2); return (byte)num != 0; } public static void Mapping(float delta) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_01c6: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) using (MappingProfiler.BeginScope(0)) { EnsureRegistrySubscriptions(); int dynamicObjectMappingRange = Config.DynamicObjectMappingRange; if (dynamicObjectMappingRange <= 0) { RemoveCachedPins(); return; } float num = (float)dynamicObjectMappingRange * (float)dynamicObjectMappingRange; Vector3 position = ((Component)Player.m_localPlayer).transform.position; KnownObjects.Clear(); StringList allowPinningAnimal = Config.AllowPinningAnimal; StringList allowPinningMonster = Config.AllowPinningMonster; bool num2 = allowPinningAnimal.Count == 0 && allowPinningMonster.Count == 0; bool notPinningTamedAnimals = Config.NotPinningTamedAnimals; Vector3 val; if (!num2) { foreach (Character allCharacter in Character.GetAllCharacters()) { if (allCharacter.IsPlayer()) { continue; } Vector3 position2 = ((Component)allCharacter).transform.position; val = position - position2; if (((Vector3)(ref val)).sqrMagnitude > num || !TryResolveCharacterIdentifier(allCharacter, out var kind, out var identifier)) { continue; } if (kind == CharacterKind.Animal) { if (!allowPinningAnimal.Contains(identifier) || (allCharacter.IsTamed() && notPinningTamedAnimals)) { continue; } } else if (!allowPinningMonster.Contains(identifier)) { continue; } AddOrUpdatePin(allCharacter, delta); } } if (Config.PinAnimalIncludesFish) { InstanceCache.Fill(FishBuffer); for (int i = 0; i < FishBuffer.Count; i++) { Fish val2 = FishBuffer[i]; val = position - ((Component)val2).transform.position; if (!(((Vector3)(ref val)).sqrMagnitude > num)) { AddOrUpdatePin((Component)(object)val2, delta); } } } if (Config.PinAnimalIncludesBird) { InstanceCache.Fill(BirdBuffer); for (int j = 0; j < BirdBuffer.Count; j++) { RandomFlyingBird val3 = BirdBuffer[j]; val = position - ((Component)val3).transform.position; if (!(((Vector3)(ref val)).sqrMagnitude > num)) { AddOrUpdatePin((Component)(object)val3, delta); } } } VehicleMapping(position, num, delta); RemoveCachedPins(KnownObjects); } } private static void VehicleMapping(Vector3 origin, float rangeSq, float delta) { //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: 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_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: 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_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: 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) if (Config.AllowPinningVehicle.Count == 0) { return; } VehicleBuffer.Clear(); InstanceCache.Fill(ShipBuffer); for (int i = 0; i < ShipBuffer.Count; i++) { VehicleBuffer.Add((Component)(object)ShipBuffer[i]); } List staticField = Reflections.GetStaticField>("m_instances"); if (staticField != null) { for (int j = 0; j < staticField.Count; j++) { VehicleBuffer.Add((Component)(object)staticField[j]); } } for (int k = 0; k < VehicleBuffer.Count; k++) { Component val = VehicleBuffer[k]; if (!Objects.GetZdoid(val, out var id)) { continue; } Vector3 position = val.transform.position; Vector3 val2 = origin - position; if (((Vector3)(ref val2)).sqrMagnitude > rangeSq) { continue; } string name = Objects.GetName(val); if (GetVehicle(name, out (string, bool) data) && data.Item2) { if (VehiclePinCache.TryGetValue(id, out var _)) { TryMarkTargetDirty(VehiclePinTargetCache, VehicleDirtyPins, id, position); continue; } PinData value2 = Map.AddPin(position, name, save: true, CreateTarget(val.gameObject, name)); VehiclePinCache.Add(id, value2); VehiclePinTargetCache[id] = position; VehiclePinVelocityCache[id] = Vector3.zero; } } } private static void AddOrUpdatePin(Character character, float delta) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_005f: 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_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) ZDOID zDOID = character.GetZDOID(); if (KnownObjects.Add(zDOID)) { string name = character.m_name; int level = character.GetLevel(); string orBuildPinName = GetOrBuildPinName(character, name, level); Vector3 position = ((Component)character).transform.position; if (!PinDataCache.TryGetValue(zDOID, out var value)) { AddPin(zDOID, position, orBuildPinName, CreateTarget(((Component)character).gameObject, name, level)); } else { UpdatePin(zDOID, value, orBuildPinName, position, delta); } } } private static string GetOrBuildPinName(Character character, string baseName, int level) { if (CharacterLevelNameCache.TryGetValue(character, out var value) && value.Level == level && (object)value.BaseName == baseName) { return value.PinName; } string text = BuildLevelPinName(baseName, level); if (value == null) { CharacterLevelNameCache.Add(character, new LevelPinNameCache { Level = level, BaseName = baseName, PinName = text }); } else { value.Level = level; value.BaseName = baseName; value.PinName = text; } return text; } private static string BuildLevelPinName(string baseName, int level) { if (level <= 1) { return baseName; } string value = Automatics.L10N.Translate("@text_automatic_mapping_creature_level_symbol"); StringBuilder stringBuilder = new StringBuilder(baseName).Append("\n"); for (int i = 1; i < level; i++) { stringBuilder.Append(value); } return stringBuilder.ToString(); } private static void AddOrUpdatePin(Component component, float delta) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) if (Objects.GetZdoid(component, out var id) && KnownObjects.Add(id)) { Vector3 position = component.transform.position; RandomFlyingBird val = (RandomFlyingBird)(object)((component is RandomFlyingBird) ? component : null); string text2; if (val != null) { string text = Objects.GetPrefabName(((Component)val).gameObject).ToLower(); text2 = "@animal_" + text; } else { text2 = Objects.GetName(component); } if (!PinDataCache.TryGetValue(id, out var value)) { AddPin(id, position, text2, CreateTarget(component.gameObject, text2)); } else { UpdatePin(id, value, value.m_name, position, delta); } } } private static void AddPin(ZDOID uniqueId, Vector3 pos, string pinName, Target target) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) PinData val = Map.AddPin(pos, pinName, save: false, target); if (PinDataCache.TryGetValue(uniqueId, out var data) && data != val) { PinKeyCache.Remove(data); Automatics.Logger.Warning(() => $"PinData is already exists: [Existing: {data.m_name}{data.m_pos}, New: {pinName}{pos}]"); } PinDataCache[uniqueId] = val; PinKeyCache[val] = uniqueId; PinTargetCache[uniqueId] = pos; PinVelocityCache[uniqueId] = Vector3.zero; } private static bool RemovePinFromCache(PinData pinData) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) if (!PinKeyCache.TryGetValue(pinData, out var value)) { return false; } PinKeyCache.Remove(pinData); PinDataCache.Remove(value); PinTargetCache.Remove(value); PinVelocityCache.Remove(value); DirtyPins.Remove(value); return true; } private static void UpdatePin(ZDOID uniqueId, PinData pinData, string pinName, Vector3 pos, float delta) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) if (!string.IsNullOrEmpty(pinData.m_name) && (object)pinData.m_name != pinName) { pinData.m_name = pinName; } TryMarkTargetDirty(PinTargetCache, DirtyPins, uniqueId, pos); } private static bool TryMarkTargetDirty(IDictionary targetCache, HashSet dirty, ZDOID uniqueId, Vector3 pos) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) if (targetCache.TryGetValue(uniqueId, out var value)) { Vector3 val = value - pos; if (((Vector3)(ref val)).sqrMagnitude < 0.01f) { return false; } } targetCache[uniqueId] = pos; dirty.Add(uniqueId); return true; } private static Target CreateTarget(GameObject prefab, string name, int level = 0) { Target result; if (level > 0) { result = default(Target); result.name = name; result.prefabName = Objects.GetPrefabName(prefab); result.metadata = new MetaData { level = level }; return result; } result = default(Target); result.name = name; result.prefabName = Objects.GetPrefabName(prefab); return result; } } internal static class StaticObjectMapping { public struct MapPinIdentify : IEquatable { public readonly ZDOID UniqueId; public readonly Vector3 Pos; private MapPinIdentify(ZDOID uniqueId, Vector3 pos) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: 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_0009: Unknown result type (might be due to invalid IL or missing references) UniqueId = uniqueId; Pos = pos; } public MapPinIdentify(ZDOID uniqueId) : this(uniqueId, Vector3.zero) { }//IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) public MapPinIdentify(Vector3 pos) : this(ZDOID.None, pos) { }//IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) public bool IsUniqueId() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) ZDOID uniqueId = UniqueId; if (((ZDOID)(ref uniqueId)).UserID != 0L) { return ((ZDOID)(ref UniqueId)).ID != 0; } return false; } public bool IsPos() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) return Pos != Vector3.zero; } public override int GetHashCode() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) ZDOID uniqueId = UniqueId; int num = ((object)(ZDOID)(ref uniqueId)).GetHashCode() * 397; Vector3 pos = Pos; return num ^ ((object)(Vector3)(ref pos)).GetHashCode(); } public bool UniqueIdEquals(ZDOID id) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) return UniqueId == id; } public bool PosEquals(Vector3 pos) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) return Pos == pos; } public bool Equals(MapPinIdentify other) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) if (IsUniqueId() && other.IsUniqueId()) { return UniqueIdEquals(other.UniqueId); } if (IsPos() && other.IsPos()) { return PosEquals(other.Pos); } return false; } } private const int ColliderBufferInitialLength = 4096; private const int ColliderBufferMaxLength = 16384; private const float FailedScanCooldownSeconds = 1f; private const float TileMarginMeters = 2f; private const int RetryTileBudgetPerFrame = 4; private const int MaxTileDepth = 4; private static Collider[] ColliderBuffer; private static Dictionary StaticObjectCache; private static readonly Lazy ObjectMaskLazy; private static readonly Lazy DungeonMaskLazy; private static readonly Dictionary PinDataCache; private static readonly Dictionary> PinKeyCache; private static readonly List FloraNodesBuffer; private static readonly HashSet SeenNetworksThisPass; private static readonly HashSet OwnedFloraPinsScratch; private static readonly HashSet StaleRemovalScratch; private static float _lastCacheUpdateTime; private static float _mappingTimer; private static Dictionary _pendingStaticObjectCache; private static bool _cacheIncomplete; private static float _failedScanAnchor; private static PendingScanSnapshot? _pendingScanSnapshot; private static readonly Queue PendingTiles; private static bool _tileFallbackSawTruncation; private static int _staticClassifierVersion; private static int _committedStaticClassifierVersion; private static readonly HashSet PendingAllowlistInvalidations; private static bool _registrySubscriptionsBound; private static int _currentSweepId; private static int _currentPassId; private static int ObjectMask => ObjectMaskLazy.Value; private static int DungeonMask => DungeonMaskLazy.Value; static StaticObjectMapping() { PendingTiles = new Queue(); PendingAllowlistInvalidations = new HashSet(); ColliderBuffer = (Collider[])(object)new Collider[4096]; ObjectMaskLazy = new Lazy(() => LayerMask.GetMask(new string[9] { "item", "piece", "piece_nonsolid", "Default", "static_solid", "Default_small", "character", "character_net", "vehicle" })); DungeonMaskLazy = new Lazy(() => LayerMask.GetMask(new string[1] { "character_trigger" })); StaticObjectCache = new Dictionary(); _pendingStaticObjectCache = new Dictionary(); PinDataCache = new Dictionary(); PinKeyCache = new Dictionary>(); FloraNodesBuffer = new List(); SeenNetworksThisPass = new HashSet(); OwnedFloraPinsScratch = new HashSet(); StaleRemovalScratch = new HashSet(); } private static bool CanMapping(float delta, bool takeInput) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //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) KeyboardShortcut staticObjectMappingKey = Config.StaticObjectMappingKey; if ((int)((KeyboardShortcut)(ref staticObjectMappingKey)).MainKey != 0) { if (takeInput) { staticObjectMappingKey = Config.StaticObjectMappingKey; return ((KeyboardShortcut)(ref staticObjectMappingKey)).IsDown(); } return false; } if (Config.StaticObjectMappingInterval <= 0f) { return false; } _mappingTimer += delta; if (_mappingTimer < Config.StaticObjectMappingInterval) { return false; } _mappingTimer = 0f; return true; } private static bool GetFlora(string name, out (string Identifier, bool IsAllowed) data) { if (ValheimObject.Flora.GetIdentify(name, out var identifier)) { data = (identifier, Config.AllowPinningFlora.Contains(identifier)); return true; } data = ("", false); return false; } private static bool GetMineral(string name, out (string Identifier, bool IsAllowed) data) { if (ValheimObject.Mineral.GetIdentify(name, out var identifier)) { data = (identifier, Config.AllowPinningMineral.Contains(identifier)); return true; } data = ("", false); return false; } private static bool GetSpawner(string name, out (string Identifier, bool IsAllowed) data) { if (ValheimObject.Spawner.GetIdentify(name, out var identifier)) { data = (identifier, Config.AllowPinningSpawner.Contains(identifier)); return true; } data = ("", false); return false; } private static bool GetOther(string name, out (string Identifier, bool IsAllowed) data) { if (MappingObject.Other.GetIdentify(name, out var identifier)) { data = (identifier, Config.AllowPinningOther.Contains(identifier)); return true; } data = ("", false); return false; } private static bool GetDungeon(string name, out (string Identifier, bool IsAllowed) data) { if (ValheimObject.Dungeon.GetIdentify(name, out var identifier)) { data = (identifier, Config.AllowPinningDungeon.Contains(identifier)); return true; } data = ("", false); return false; } private static bool GetSpot(string name, out (string Identifier, bool IsAllowed) data) { if (ValheimObject.Spot.GetIdentify(name, out var identifier)) { data = (identifier, Config.AllowPinningSpot.Contains(identifier)); return true; } data = ("", false); return false; } private static void RemoveCache(PinData pinData) { RemovePinFromCache(pinData); } [UsedImplicitly] public static void OnObjectDestroy(Component component, ZNetView zNetView) { //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) try { if (!Config.EnableAutomaticMapping || !Config.RemovePinsOfDestroyedObject || !zNetView.IsValid() || !zNetView.IsOwner()) { return; } PinData val = null; string name = Objects.GetName(component); if (GetFlora(name, out (string, bool) data)) { if (!data.Item2) { return; } FloraNode component2 = component.GetComponent(); if (!Object.op_Implicit((Object)(object)component2)) { val = Map.RemovePin(component.transform.position); } else if (component2.Network.NodeCount <= 1) { val = Map.RemovePin(component2.Network.Center); } } else if (GetMineral(name, out data)) { if (!data.Item2) { return; } val = Map.RemovePin(GetMineralRemovalCenter(component)); } else if (GetSpawner(name, out data) || GetOther(name, out data)) { if (!data.Item2) { return; } val = Map.RemovePin(component.transform.position); } if (val != null) { RemoveCache(val); } } finally { MineRock5 val2 = (MineRock5)(object)((component is MineRock5) ? component : null); if (val2 != null) { MineRock5Cache.Unregister(val2); } } } private static Vector3 GetMineralRemovalCenter(Component component) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) MineRock5 val = (MineRock5)(object)((component is MineRock5) ? component : null); if (val != null && MineRock5Cache.TryGetSnapshot(val, out var snapshot) && snapshot.ColliderCount > 0) { return snapshot.Center; } Collider[] array = Array.Empty(); MineRock val2 = (MineRock)(object)((component is MineRock) ? component : null); IReadOnlyCollection readOnlyCollection; if (val2 == null) { Destructible val3 = (Destructible)(object)((component is Destructible) ? component : null); if (val3 != null) { Collider componentInChildren = ((Component)val3).GetComponentInChildren(); readOnlyCollection = (IReadOnlyCollection)((!Object.op_Implicit((Object)(object)componentInChildren)) ? ((Array)array) : ((Array)new Collider[1] { componentInChildren })); } else { readOnlyCollection = (IReadOnlyCollection)(object)array; } } else { readOnlyCollection = (IReadOnlyCollection)(object)(Reflections.GetField(val2, "m_hitAreas") ?? array); } if (readOnlyCollection.Count == 0) { return component.transform.position; } return readOnlyCollection.Aggregate(Vector3.zero, delegate(Vector3 current, Collider collider) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) Bounds bounds = collider.bounds; return current + ((Bounds)(ref bounds)).center; }) / (float)readOnlyCollection.Count; } public static void Cleanup() { StaticObjectCache.Clear(); _pendingStaticObjectCache.Clear(); PinDataCache.Clear(); PinKeyCache.Clear(); SeenNetworksThisPass.Clear(); OwnedFloraPinsScratch.Clear(); StaleRemovalScratch.Clear(); PendingTiles.Clear(); _tileFallbackSawTruncation = false; _pendingScanSnapshot = null; _cacheIncomplete = false; _failedScanAnchor = 0f; _lastCacheUpdateTime = 0f; _mappingTimer = 0f; _committedStaticClassifierVersion = _staticClassifierVersion; PendingAllowlistInvalidations.Clear(); _currentSweepId = 0; _currentPassId = 0; } public static void RemoveCachedPins() { if (PinDataCache.Count == 0) { return; } StaleRemovalScratch.Clear(); foreach (KeyValuePair item in PinDataCache) { StaleRemovalScratch.Add(item.Value.PinData); } foreach (PinData item2 in StaleRemovalScratch) { RemovePinFromCache(item2); if (!item2.m_save) { Map.RemovePin(item2); } } StaleRemovalScratch.Clear(); } public static void OnRemovePin(PinData pinData) { RemovePinFromCache(pinData); } public static bool SetSaveFlag(PinData pinData) { if (!RemovePinFromCache(pinData)) { return false; } pinData.m_save = true; Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)2, Automatics.L10N.Localize("@message_automatic_mapping_pin_saved", pinData.m_name.Replace("\n", "")), 0, (Sprite)null); } return true; } public static void Mapping(float delta, bool takeInput) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_0198: Unknown result type (might be due to invalid IL or missing references) //IL_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) using (MappingProfiler.BeginScope(1)) { EnsureRegistrySubscriptions(); if (Config.StaticObjectMappingRange <= 0) { RemoveCachedPins(); } else { if (!CanMapping(delta, takeInput)) { return; } Vector3 position = ((Component)Player.m_localPlayer).transform.position; ApplyTargetedInvalidations(); CacheStaticObjects(position); BeginPass(); int staticObjectMappingRange = Config.StaticObjectMappingRange; float num = (float)staticObjectMappingRange * (float)staticObjectMappingRange; Vector3 val; foreach (KeyValuePair item in StaticObjectCache) { Collider key = item.Key; ClassifiedStaticObject value = item.Value; Component component = value.Component; if (!Object.op_Implicit((Object)(object)key) || !Object.op_Implicit((Object)(object)component)) { continue; } Vector3 position2 = component.transform.position; val = position - position2; if (!(((Vector3)(ref val)).sqrMagnitude > num) && ZNetScene.instance.IsAreaReady(position2)) { string sourceToken = value.SourceToken; switch (value.Kind) { case PinKind.Flora: FloraMapping(component, sourceToken); break; case PinKind.Mineral: MineralMapping(component, sourceToken); break; case PinKind.Spawner: SpawnerMapping(component, sourceToken); break; case PinKind.Other: OtherMapping(component, sourceToken); break; case PinKind.Portal: PortalMapping(component, sourceToken); break; } } } int locationMappingRange = Config.LocationMappingRange; float num2 = (float)locationMappingRange * (float)locationMappingRange; foreach (KeyValuePair locationInstance in ZoneSystem.instance.m_locationInstances) { LocationInstance value2 = locationInstance.Value; val = position - value2.m_position; if (!(((Vector3)(ref val)).sqrMagnitude > num2) && !DungeonMapping(value2)) { SpotMapping(value2); } } EndPassAndPruneStale(); } } } private static void BeginPass() { _currentPassId++; SeenNetworksThisPass.Clear(); if (!_cacheIncomplete) { _currentSweepId++; } } private static void EndPassAndPruneStale() { if (_cacheIncomplete || PinDataCache.Count == 0) { return; } StaleRemovalScratch.Clear(); foreach (KeyValuePair> item in PinKeyCache) { PinData key = item.Key; int num = int.MinValue; foreach (MapPinIdentify item2 in item.Value) { if (PinDataCache.TryGetValue(item2, out var value) && value.LastSeenSweep > num) { num = value.LastSeenSweep; } } if (num < _currentSweepId) { StaleRemovalScratch.Add(key); } } foreach (PinData item3 in StaleRemovalScratch) { RemovePinFromCache(item3); if (!item3.m_save) { Map.RemovePin(item3); } } StaleRemovalScratch.Clear(); } private static void MarkSeen(MapPinIdentify identify) { if (PinDataCache.TryGetValue(identify, out var value)) { value.LastSeenSweep = _currentSweepId; } } private static void MarkSeen(IEnumerable nodes) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) foreach (FloraNode node in nodes) { MarkSeen(new MapPinIdentify(node.UniqueId)); } } private static void CacheStaticObjects(Vector3 origin) { //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0110: 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_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_0207: Unknown result type (might be due to invalid IL or missing references) //IL_0208: Unknown result type (might be due to invalid IL or missing references) //IL_02cd: Unknown result type (might be due to invalid IL or missing references) //IL_02d0: Unknown result type (might be due to invalid IL or missing references) using (MappingProfiler.BeginScope(2)) { float time = Time.time; if (_cacheIncomplete && PendingTiles.Count == 0) { if (time - _failedScanAnchor < 1f) { return; } } else if (!_cacheIncomplete && time - _lastCacheUpdateTime < Config.StaticObjectCachingInterval) { return; } int staticObjectMappingRange = Config.StaticObjectMappingRange; if (staticObjectMappingRange <= 0) { return; } int objectMask = ObjectMask; int staticClassifierVersion = _staticClassifierVersion; float num = ComputeOriginTolerance(staticObjectMappingRange); if (_pendingScanSnapshot.HasValue) { PendingScanSnapshot value = _pendingScanSnapshot.Value; if (value.Mask != objectMask || !Mathf.Approximately(value.Range, (float)staticObjectMappingRange) || value.StaticClassifierVersion != staticClassifierVersion || Vector3.Distance(origin, value.Origin) > num) { _pendingStaticObjectCache.Clear(); PendingTiles.Clear(); _tileFallbackSawTruncation = false; _pendingScanSnapshot = null; } } if (PendingTiles.Count > 0 && _pendingScanSnapshot.HasValue) { ProcessTileBudget(_pendingScanSnapshot.Value, origin, num, time, staticClassifierVersion); return; } Collider[] buffer = ColliderBuffer; int num2 = Physics.OverlapSphereNonAlloc(origin, (float)staticObjectMappingRange * 1.5f, buffer, objectMask); if (num2 >= buffer.Length) { int newLength = Mathf.Min(buffer.Length * 2, 16384); if (newLength > buffer.Length) { ColliderBuffer = (Collider[])(object)new Collider[newLength]; Automatics.Logger.Warning(() => $"[AutomaticMapping] Physics scan saturated at {buffer.Length}; " + $"grew ColliderBuffer to {newLength}, retrying after cooldown."); } else { Automatics.Logger.Warning(() => "[AutomaticMapping] Physics scan saturated at buffer ceiling " + $"({buffer.Length}); switching to OverlapBox tile fallback."); SeedInitialTiles(origin, staticObjectMappingRange); } _cacheIncomplete = true; _failedScanAnchor = time; _pendingStaticObjectCache.Clear(); PendingScanSnapshot value2 = default(PendingScanSnapshot); value2.Origin = origin; value2.Range = staticObjectMappingRange; value2.Mask = objectMask; value2.StaticClassifierVersion = staticClassifierVersion; _pendingScanSnapshot = value2; return; } Dictionary pendingStaticObjectCache = _pendingStaticObjectCache; pendingStaticObjectCache.Clear(); for (int i = 0; i < num2; i++) { Collider val = buffer[i]; if (!((Object)(object)val == (Object)null)) { ClassifiedStaticObject? classifiedStaticObject = ClassifyStaticObject(val); if (classifiedStaticObject.HasValue) { pendingStaticObjectCache[val] = classifiedStaticObject.Value; } } } if (_pendingScanSnapshot.HasValue) { PendingScanSnapshot value3 = _pendingScanSnapshot.Value; if (value3.Mask != objectMask || !Mathf.Approximately(value3.Range, (float)staticObjectMappingRange) || value3.StaticClassifierVersion != staticClassifierVersion || Vector3.Distance(origin, value3.Origin) > num) { _pendingStaticObjectCache.Clear(); PendingTiles.Clear(); _tileFallbackSawTruncation = false; _pendingScanSnapshot = null; _cacheIncomplete = true; _failedScanAnchor = time; return; } } CommitPendingSwap(time, staticClassifierVersion); } } private static void ProcessTileBudget(PendingScanSnapshot snapshot, Vector3 origin, float originTolerance, float now, int classifierVersion) { //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) float num = snapshot.Range * 1.5f; Collider[] buffer = ColliderBuffer; int mask = snapshot.Mask; Dictionary pendingStaticObjectCache = _pendingStaticObjectCache; int num2 = 4; Vector3 val = default(Vector3); while (num2 > 0 && PendingTiles.Count > 0) { PendingTile parent = PendingTiles.Dequeue(); num2--; ((Vector3)(ref val))..ctor(parent.HalfXZ + 2f, num, parent.HalfXZ + 2f); int num3 = Physics.OverlapBoxNonAlloc(parent.Center, val, buffer, Quaternion.identity, mask); if (num3 >= buffer.Length) { if (parent.Depth < 4) { SplitTile(parent); continue; } _tileFallbackSawTruncation = true; Automatics.Logger.Warning(() => $"[AutomaticMapping] OverlapBox tile at depth {4} " + $"saturated {buffer.Length}; classifying truncated results. Pins " + "in this sub-region may be incomplete until the player moves."); } for (int i = 0; i < num3; i++) { Collider val2 = buffer[i]; if (!((Object)(object)val2 == (Object)null)) { ClassifiedStaticObject? classifiedStaticObject = ClassifyStaticObject(val2); if (classifiedStaticObject.HasValue) { pendingStaticObjectCache[val2] = classifiedStaticObject.Value; } } } } if (PendingTiles.Count <= 0) { if (Vector3.Distance(origin, snapshot.Origin) > originTolerance) { _pendingStaticObjectCache.Clear(); _tileFallbackSawTruncation = false; _pendingScanSnapshot = null; _failedScanAnchor = now; } else if (_tileFallbackSawTruncation) { CommitPendingSwapDegraded(now); } else { CommitPendingSwap(now, classifierVersion); } } } private static void CommitPendingSwap(float now, int classifierVersion) { Dictionary staticObjectCache = StaticObjectCache; StaticObjectCache = _pendingStaticObjectCache; staticObjectCache.Clear(); _pendingStaticObjectCache = staticObjectCache; _lastCacheUpdateTime = now; _cacheIncomplete = false; _pendingScanSnapshot = null; _tileFallbackSawTruncation = false; PendingTiles.Clear(); _committedStaticClassifierVersion = classifierVersion; } private static void CommitPendingSwapDegraded(float now) { Dictionary staticObjectCache = StaticObjectCache; StaticObjectCache = _pendingStaticObjectCache; staticObjectCache.Clear(); _pendingStaticObjectCache = staticObjectCache; PendingTiles.Clear(); _pendingScanSnapshot = null; _tileFallbackSawTruncation = false; _failedScanAnchor = now; } private static void SeedInitialTiles(Vector3 origin, float range) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) PendingTiles.Clear(); EnqueueQuadrants(origin, range * 0.75f, 1); } private static void SplitTile(PendingTile parent) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) EnqueueQuadrants(parent.Center, parent.HalfXZ * 0.5f, parent.Depth + 1); } private static void EnqueueQuadrants(Vector3 center, float childHalf, int depth) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0037: 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_0044: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < 2; i++) { for (int j = 0; j < 2; j++) { float num = ((i == 0) ? (0f - childHalf) : childHalf); float num2 = ((j == 0) ? (0f - childHalf) : childHalf); PendingTiles.Enqueue(new PendingTile { Center = new Vector3(center.x + num, center.y, center.z + num2), HalfXZ = childHalf, Depth = depth }); } } } private static float ComputeOriginTolerance(float mappingRange) { if (mappingRange <= 4f) { return 0f; } float num = 0.5f * mappingRange - 2f; if (!(num < 1f)) { return num; } return 0.1f; } private static ClassifiedStaticObject? ClassifyStaticObject(Collider collider) { //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) IDestructible componentInParent = ((Component)collider).GetComponentInParent(); Component val = (Component)(object)((componentInParent is Component) ? componentInParent : null); if (!Object.op_Implicit((Object)(object)val)) { Interactable componentInParent2 = ((Component)collider).GetComponentInParent(); val = (Component)(object)((componentInParent2 is Component) ? componentInParent2 : null); } if (!Object.op_Implicit((Object)(object)val)) { Hoverable componentInParent3 = ((Component)collider).GetComponentInParent(); val = (Component)(object)((componentInParent3 is Component) ? componentInParent3 : null); } if (!Object.op_Implicit((Object)(object)val)) { return null; } string name = Objects.GetName(val); if (string.IsNullOrEmpty(name)) { return null; } if (!ClassifyStaticComponent(val, name, out var kind, out var identifier)) { return null; } if (kind == PinKind.Portal) { Component component = (Component)(object)val.GetComponent(); if (Object.op_Implicit((Object)(object)component)) { val = component; name = Objects.GetName(val); } } ClassifiedStaticObject value = default(ClassifiedStaticObject); value.Component = val; value.Kind = kind; value.Identifier = identifier; value.Position = val.transform.position; value.SourceToken = name; return value; } private static bool ClassifyStaticComponent(Component component, string sourceToken, out PinKind kind, out string identifier) { if (ClassifyStaticComponentSourceToken(sourceToken, out kind, out identifier)) { return true; } if (Object.op_Implicit((Object)(object)component.GetComponent())) { kind = PinKind.Portal; identifier = string.Empty; return true; } kind = PinKind.Flora; identifier = string.Empty; return false; } private static bool ClassifyStaticComponentSourceToken(string sourceToken, out PinKind kind, out string identifier) { if (GetFlora(sourceToken, out (string, bool) data)) { kind = PinKind.Flora; (identifier, _) = data; return true; } if (GetMineral(sourceToken, out data)) { kind = PinKind.Mineral; (identifier, _) = data; return true; } if (GetSpawner(sourceToken, out data)) { kind = PinKind.Spawner; (identifier, _) = data; return true; } if (GetOther(sourceToken, out data)) { kind = PinKind.Other; (identifier, _) = data; return true; } kind = PinKind.Flora; identifier = string.Empty; return false; } private static bool ClassifyStaticLocation(string prefabName, out PinKind kind, out string identifier) { if (GetDungeon(prefabName, out (string, bool) data)) { kind = PinKind.Dungeon; (identifier, _) = data; return true; } if (GetSpot(prefabName, out data)) { kind = PinKind.Spot; (identifier, _) = data; return true; } kind = PinKind.Flora; identifier = string.Empty; return false; } private static void EnsureRegistrySubscriptions() { if (!_registrySubscriptionsBound) { _registrySubscriptionsBound = true; ValheimObject.RegistryChanged += OnValheimObjectRegistryChanged; Config.StaticAllowlistChanged += OnStaticAllowlistChanged; } } private static void OnValheimObjectRegistryChanged(ValheimObject obj) { if (obj == ValheimObject.Flora || obj == ValheimObject.Mineral || obj == ValheimObject.Spawner || obj == ValheimObject.Dungeon || obj == ValheimObject.Spot || obj == MappingObject.Other) { _staticClassifierVersion++; } } private static void OnStaticAllowlistChanged(ValheimObject registry) { PendingAllowlistInvalidations.Add(registry); } private static ValheimObject RegistryForKind(PinKind kind) { return kind switch { PinKind.Flora => ValheimObject.Flora, PinKind.Mineral => ValheimObject.Mineral, PinKind.Spawner => ValheimObject.Spawner, PinKind.Other => MappingObject.Other, PinKind.Dungeon => ValheimObject.Dungeon, PinKind.Spot => ValheimObject.Spot, _ => null, }; } private static void ApplyTargetedInvalidations() { bool flag = _committedStaticClassifierVersion != _staticClassifierVersion; bool flag2 = PendingAllowlistInvalidations.Count > 0; if (!flag && !flag2) { return; } if (PinDataCache.Count == 0) { if (flag) { _committedStaticClassifierVersion = _staticClassifierVersion; _lastCacheUpdateTime = 0f; } PendingAllowlistInvalidations.Clear(); return; } StaleRemovalScratch.Clear(); foreach (KeyValuePair item in PinDataCache) { PinCacheEntry value = item.Value; if (value?.PinData != null && ShouldRetireEntry(value, flag)) { StaleRemovalScratch.Add(value.PinData); } } foreach (PinData item2 in StaleRemovalScratch) { RemovePinFromCache(item2); if (!item2.m_save) { Map.RemovePin(item2); } } StaleRemovalScratch.Clear(); if (flag) { _committedStaticClassifierVersion = _staticClassifierVersion; _lastCacheUpdateTime = 0f; } PendingAllowlistInvalidations.Clear(); } private static bool ShouldRetireEntry(PinCacheEntry entry, bool registryChanged) { if (entry.Domain == PinSourceDomain.Component && entry.Kind == PinKind.Portal) { return false; } if (!registryChanged) { ValheimObject valheimObject = RegistryForKind(entry.Kind); if (valheimObject == null || !PendingAllowlistInvalidations.Contains(valheimObject)) { return false; } } switch (entry.Domain) { case PinSourceDomain.Component: if (registryChanged) { if (!ClassifyStaticComponentSourceToken(entry.SourceToken, out var kind2, out var identifier2)) { return true; } if (kind2 != entry.Kind || identifier2 != entry.Identifier) { return true; } } return !IsAllowedForKind(entry.Kind, entry.Identifier); case PinSourceDomain.Location: if (registryChanged) { if (!ClassifyStaticLocation(entry.SourceToken, out var kind, out var identifier)) { return true; } if (kind != entry.Kind || identifier != entry.Identifier) { return true; } } return !IsAllowedForKind(entry.Kind, entry.Identifier); default: return false; } } private static bool IsAllowedForKind(PinKind kind, string identifier) { return kind switch { PinKind.Flora => Config.AllowPinningFlora.Contains(identifier), PinKind.Mineral => Config.AllowPinningMineral.Contains(identifier), PinKind.Spawner => Config.AllowPinningSpawner.Contains(identifier), PinKind.Other => Config.AllowPinningOther.Contains(identifier), PinKind.Portal => Config.AllowPinningPortal, PinKind.Dungeon => Config.AllowPinningDungeon.Contains(identifier), PinKind.Spot => Config.AllowPinningSpot.Contains(identifier), _ => false, }; } private static bool FloraMapping(Component component, string name) { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00db: 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_00fc: Unknown result type (might be due to invalid IL or missing references) if (!GetFlora(name, out (string, bool) data)) { return false; } if (!data.Item2) { return true; } if (!Objects.GetZdoid(component, out var id)) { return true; } string name2; string text = (ValheimObject.Flora.GetName(data.Item1, out name2) ? name2 : name); FloraNode floraNode = FloraNode.Find(id); if (!Object.op_Implicit((Object)(object)floraNode) || !floraNode.IsValid()) { return true; } FloraNetwork network = floraNode.Network; if (network == null) { return true; } if (network.IsDirty) { HandleDirtyFloraCluster(component, network, data.Item1, name, text); SeenNetworksThisPass.Add(network); return true; } if (!SeenNetworksThisPass.Add(network)) { return true; } network.FillValidNodes(FloraNodesBuffer); if (TryGetCachedPin(FloraNodesBuffer, out var pinData)) { CachePin(FloraNodesBuffer, pinData, PinKind.Flora, data.Item1, name, PinSourceDomain.Component); return true; } Vector3 center = network.Center; if (Map.GetClosestPin(center) != null) { return true; } string pinName = ComputeFloraPinName(text, network.NodeCount); PinData pinData2 = AddPin(id, center, pinName, Config.SaveStaticObjectPins, CreateTarget(component.gameObject, text), PinKind.Flora, data.Item1, name, PinSourceDomain.Component); CachePin(FloraNodesBuffer, pinData2, PinKind.Flora, data.Item1, name, PinSourceDomain.Component); return true; } private static void HandleDirtyFloraCluster(Component component, FloraNetwork network, string identifier, string sourceToken, string displayName) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) network.FillValidNodes(FloraNodesBuffer); OwnedFloraPinsScratch.Clear(); foreach (FloraNode item in FloraNodesBuffer) { if (PinDataCache.TryGetValue(new MapPinIdentify(item.UniqueId), out var value) && value.PinData != null) { OwnedFloraPinsScratch.Add(value.PinData); } } network.Update(); PinData val = null; foreach (PinData item2 in OwnedFloraPinsScratch) { if (val == null) { val = item2; continue; } RemovePinFromCache(item2); Map.RemovePin(item2); } Vector3 center = network.Center; string name = ComputeFloraPinName(displayName, network.NodeCount); if (val != null) { Map.MovePin(val, center); val.m_name = name; RemovePinFromCache(val); CachePin(FloraNodesBuffer, val, PinKind.Flora, identifier, sourceToken, PinSourceDomain.Component); } else if (Map.GetClosestPin(center) == null) { PinData pinData = Map.AddPin(center, name, Config.SaveStaticObjectPins, CreateTarget(component.gameObject, displayName)); CachePin(FloraNodesBuffer, pinData, PinKind.Flora, identifier, sourceToken, PinSourceDomain.Component); } OwnedFloraPinsScratch.Clear(); } private static string ComputeFloraPinName(string displayName, int nodeCount) { if (nodeCount <= 1) { return displayName; } return Automatics.L10N.LocalizeTextOnly("@text_automatic_mapping_flora_cluster_pin_name", displayName, nodeCount); } private static bool MineralMapping(Component component, string name) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0064: 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_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) string text = name; if (!GetMineral(text, out (string, bool) data)) { return false; } if (!data.Item2) { return true; } if (!Objects.GetZdoid(component, out var id)) { return true; } MapPinIdentify identify = new MapPinIdentify(id); if (TryGetCachedPin(identify, out var _)) { MarkSeen(identify); return true; } if (ValheimObject.Mineral.GetName(data.Item1, out var name2)) { name = name2; } if (!TryGetMineralPosition(component, out var position, out var maxHeight)) { return true; } if (Map.GetClosestPin(position) != null) { return true; } if (Config.NeedToEquipWishboneForUndergroundMinerals && maxHeight < ZoneSystem.instance.GetGroundHeight(position) && (from x in ((Humanoid)Player.m_localPlayer).GetInventory().GetEquippedItems() select x.m_shared.m_name).All((string x) => x != "$item_wishbone")) { return true; } AddPin(id, position, name, CreateTarget(component.gameObject, name), PinKind.Mineral, data.Item1, text, PinSourceDomain.Component); return true; } private static bool TryGetMineralPosition(Component component, out Vector3 position, out float maxHeight) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_007f: 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_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008c: 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_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) position = Vector3.zero; maxHeight = float.MinValue; MineRock5 val = (MineRock5)(object)((component is MineRock5) ? component : null); if (val != null) { if (!MineRock5Cache.TryGetOrBuildSnapshotAlive(val, out var snapshot)) { return false; } if (snapshot.ColliderCount == 0) { return false; } if (snapshot.Center == Vector3.zero) { return false; } position = snapshot.Center; maxHeight = snapshot.MaxHeight; return true; } Collider[] mineralColliders = GetMineralColliders(component); int num = 0; Vector3 val2 = Vector3.zero; for (int i = 0; i < mineralColliders.Length; i++) { Bounds bounds = mineralColliders[i].bounds; val2 += ((Bounds)(ref bounds)).center; if (((Bounds)(ref bounds)).max.y > maxHeight) { maxHeight = ((Bounds)(ref bounds)).max.y; } num++; } if (num == 0 || val2 == Vector3.zero) { return false; } position = val2 / (float)num; return true; } private static Collider[] GetMineralColliders(Component component) { Collider[] result = Array.Empty(); MineRock val = (MineRock)(object)((component is MineRock) ? component : null); if (val == null) { Destructible val2 = (Destructible)(object)((component is Destructible) ? component : null); if (val2 != null) { Collider componentInChildren = ((Component)val2).GetComponentInChildren(); if (Object.op_Implicit((Object)(object)componentInChildren)) { return (Collider[])(object)new Collider[1] { componentInChildren }; } return result; } return result; } Collider[] field = Reflections.GetField(val, "m_hitAreas"); if (field == null) { return result; } if (!Objects.GetZNetView((Component)(object)val, out var zNetView)) { return result; } for (int i = 0; i < field.Length; i++) { if (zNetView.GetZDO().GetFloat("Health" + i, val.m_health) <= 0f) { return result; } } return field; } private static bool SpawnerMapping(Component component, string name) { //IL_0026: 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_0061: 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_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) string text = name; if (!GetSpawner(text, out (string, bool) data)) { return false; } if (!data.Item2) { return true; } if (!Objects.GetZdoid(component, out var id)) { return true; } MapPinIdentify identify = new MapPinIdentify(id); if (TryGetCachedPin(identify, out var _)) { MarkSeen(identify); return true; } if (ValheimObject.Spawner.GetName(data.Item1, out var name2)) { name = name2; } Vector3 position = component.transform.position; if (Map.GetClosestPin(position) == null) { AddPin(id, position, name, CreateTarget(component.gameObject, name), PinKind.Spawner, data.Item1, text, PinSourceDomain.Component); } return true; } private static bool OtherMapping(Component component, string name) { //IL_0026: 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_0061: 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_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) string text = name; if (!GetOther(text, out (string, bool) data)) { return false; } if (!data.Item2) { return true; } if (!Objects.GetZdoid(component, out var id)) { return true; } MapPinIdentify identify = new MapPinIdentify(id); if (TryGetCachedPin(identify, out var _)) { MarkSeen(identify); return true; } if (MappingObject.Other.GetName(data.Item1, out var name2)) { name = name2; } Vector3 position = component.transform.position; if (Map.GetClosestPin(position) == null) { AddPin(id, position, name, CreateTarget(component.gameObject, name), PinKind.Other, data.Item1, text, PinSourceDomain.Component); } return true; } private static bool PortalMapping(Component component, string name) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0077: 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_008c: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) if (!Config.AllowPinningPortal) { return false; } TeleportWorld component2 = component.GetComponent(); if (!Object.op_Implicit((Object)(object)component2)) { return false; } if (!Objects.GetZdoid(component, out var id)) { return true; } MapPinIdentify identify = new MapPinIdentify(id); string text = component2.GetText(); string text2 = (string.IsNullOrEmpty(text) ? Automatics.L10N.Translate("@text_automatic_mapping_empty_portal_tag") : text); if (TryGetCachedPin(identify, out var pinData)) { pinData.m_name = text2; MarkSeen(identify); return true; } Vector3 position = component.transform.position; pinData = Map.GetClosestPin(position); if (pinData == null) { AddPin(id, position, text2, save: true, CreateTarget(component.gameObject, name), PinKind.Portal, string.Empty, name, PinSourceDomain.Component); } else { pinData.m_name = text2; } return true; } private static bool DungeonMapping(LocationInstance instance) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0057: 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_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) string prefabName = instance.m_location.m_prefabName; if (!GetDungeon(prefabName, out (string, bool) data)) { return false; } if (!data.Item2) { return true; } if (!ValheimObject.Dungeon.GetName(data.Item1, out var name)) { name = "@location_" + prefabName.ToLower(); } Vector3 position = instance.m_position; float exteriorRadius = instance.m_location.m_exteriorRadius; List<(Collider, Teleport, float)> insideSphere = Objects.GetInsideSphere(position, exteriorRadius, GetTeleport, ColliderBuffer, DungeonMask); Collider val = null; float num = float.MaxValue; for (int i = 0; i < insideSphere.Count; i++) { (Collider, Teleport, float) tuple = insideSphere[i]; if (!(tuple.Item3 >= num)) { (val, _, num) = tuple; } } PinData pinData; if ((Object)(object)val != (Object)null) { Bounds bounds = val.bounds; Vector3 center = ((Bounds)(ref bounds)).center; MapPinIdentify identify = new MapPinIdentify(center); if (TryGetCachedPin(identify, out pinData)) { MarkSeen(identify); return true; } if (Map.GetClosestPin(center) == null) { AddPin(ZDOID.None, center, name, CreateTarget(prefabName, name), PinKind.Dungeon, data.Item1, prefabName, PinSourceDomain.Location); } return true; } MapPinIdentify identify2 = new MapPinIdentify(position); if (TryGetCachedPin(identify2, out pinData)) { MarkSeen(identify2); return true; } if (Map.GetClosestPin(position, exteriorRadius, (PinData x) => x.m_name == name) == null) { AddPin(ZDOID.None, position, name, CreateTarget(prefabName, name), PinKind.Dungeon, data.Item1, prefabName, PinSourceDomain.Location); Automatics.Logger.Warning(() => "Dungeon " + name + " has no entrance."); } return true; static Teleport GetTeleport(Collider collider) { return ((Component)collider).GetComponent(); } } private static bool SpotMapping(LocationInstance instance) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) string prefabName = instance.m_location.m_prefabName; if (!GetSpot(prefabName, out (string, bool) data)) { return false; } if (!data.Item2) { return true; } Vector3 position = instance.m_position; MapPinIdentify identify = new MapPinIdentify(position); if (TryGetCachedPin(identify, out var _)) { MarkSeen(identify); return true; } if (!ValheimObject.Spot.GetName(data.Item1, out var name)) { name = "@location_" + prefabName.ToLower(); } if (Map.GetClosestPin(position) == null) { AddPin(ZDOID.None, position, name, CreateTarget(prefabName, name), PinKind.Spot, data.Item1, prefabName, PinSourceDomain.Location); } return true; } private static PinData AddPin(ZDOID uniqueId, Vector3 pos, string pinName, bool save, Target target, PinKind kind, string identifier, string sourceToken, PinSourceDomain domain) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) PinData val = Map.AddPin(pos, pinName, save, target); MapPinIdentify mapPinIdentify = (((ZDOID)(ref uniqueId)).IsNone() ? new MapPinIdentify(pos) : new MapPinIdentify(uniqueId)); if (PinDataCache.TryGetValue(mapPinIdentify, out var existing) && existing.PinData != val) { Automatics.Logger.Warning(() => $"PinData is already exists: [Existing: {existing.PinData.m_name}{existing.PinData.m_pos}, New: {pinName}{pos}]"); } CachePin(mapPinIdentify, val, kind, identifier, sourceToken, domain); return val; } private static void AddPin(ZDOID uniqueId, Vector3 pos, string pinName, Target target, PinKind kind, string identifier, string sourceToken, PinSourceDomain domain) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) AddPin(uniqueId, pos, pinName, Config.SaveStaticObjectPins, target, kind, identifier, sourceToken, domain); } private static bool TryGetCachedPin(MapPinIdentify identify, out PinData pinData) { if (PinDataCache.TryGetValue(identify, out var value) && value?.PinData != null) { pinData = value.PinData; return true; } pinData = null; return false; } private static bool TryGetCachedPin(IEnumerable nodes, out PinData pinData) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) foreach (FloraNode node in nodes) { if (TryGetCachedPin(new MapPinIdentify(node.UniqueId), out pinData)) { return true; } } pinData = null; return false; } private static void CachePin(IEnumerable nodes, PinData pinData, PinKind kind, string identifier, string sourceToken, PinSourceDomain domain) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) foreach (FloraNode node in nodes) { CachePin(new MapPinIdentify(node.UniqueId), pinData, kind, identifier, sourceToken, domain); } } private static void CachePin(MapPinIdentify identify, PinData pinData, PinKind kind, string identifier, string sourceToken, PinSourceDomain domain) { if (PinDataCache.TryGetValue(identify, out var value)) { if (value.PinData == pinData) { value.Kind = kind; value.Identifier = identifier; value.SourceToken = sourceToken; value.Domain = domain; value.LastSeenSweep = _currentSweepId; return; } RemovePinKey(value.PinData, identify); } PinDataCache[identify] = new PinCacheEntry { PinData = pinData, Kind = kind, Identifier = identifier, SourceToken = sourceToken, Domain = domain, LastSeenSweep = _currentSweepId }; if (!PinKeyCache.TryGetValue(pinData, out var value2)) { value2 = new HashSet(); PinKeyCache.Add(pinData, value2); } value2.Add(identify); } private static bool RemovePinFromCache(PinData pinData) { if (!PinKeyCache.TryGetValue(pinData, out var value)) { return false; } PinKeyCache.Remove(pinData); foreach (MapPinIdentify item in value) { PinDataCache.Remove(item); } return true; } private static void RemovePinKey(PinData pinData, MapPinIdentify identify) { if (PinKeyCache.TryGetValue(pinData, out var value)) { value.Remove(identify); if (value.Count == 0) { PinKeyCache.Remove(pinData); } } } private static Target CreateTarget(string prefabName, string name) { Target result = default(Target); result.name = name; result.prefabName = prefabName; return result; } private static Target CreateTarget(GameObject prefab, string name) { return CreateTarget(Objects.GetPrefabName(prefab), name); } } internal static class Config { private const string Section = "automatic_mapping"; private static ConfigEntry _module; private static ConfigEntry _enableAutomaticMapping; private static ConfigEntry _dynamicObjectMappingRange; private static ConfigEntry _staticObjectMappingRange; private static ConfigEntry _locationMappingRange; private static ConfigEntry _allowPinningAnimal; private static ConfigEntry _allowPinningMonster; private static ConfigEntry _allowPinningFlora; private static ConfigEntry _allowPinningMineral; private static ConfigEntry _allowPinningSpawner; private static ConfigEntry _allowPinningOther; private static ConfigEntry _allowPinningDungeon; private static ConfigEntry _allowPinningSpot; private static ConfigEntry _allowPinningVehicle; private static ConfigEntry _allowPinningPortal; private static ConfigEntry _notPinningTamedAnimals; private static ConfigEntry _staticObjectMappingInterval; private static ConfigEntry _staticObjectCachingInterval; private static ConfigEntry _saveStaticObjectPins; private static ConfigEntry _removePinsOfDestroyedObject; private static ConfigEntry _floraPinMergeRange; private static ConfigEntry _needToEquipWishboneForUndergroundMinerals; private static ConfigEntry _staticObjectMappingKey; private static ConfigEntry _navigationStartKey; private static ConfigEntry _mappingPerformanceLog; public static bool ModuleDisabled => _module.Value == AutomaticsModule.Disabled; public static bool EnableAutomaticMapping => _enableAutomaticMapping.Value; public static int DynamicObjectMappingRange => _dynamicObjectMappingRange.Value; public static int StaticObjectMappingRange => _staticObjectMappingRange.Value; public static int LocationMappingRange => _locationMappingRange.Value; public static StringList AllowPinningAnimal => _allowPinningAnimal.Value; public static StringList AllowPinningMonster => _allowPinningMonster.Value; public static StringList AllowPinningFlora => _allowPinningFlora.Value; public static StringList AllowPinningMineral => _allowPinningMineral.Value; public static StringList AllowPinningSpawner => _allowPinningSpawner.Value; public static StringList AllowPinningDungeon => _allowPinningDungeon.Value; public static StringList AllowPinningSpot => _allowPinningSpot.Value; public static StringList AllowPinningOther => _allowPinningOther.Value; public static StringList AllowPinningVehicle => _allowPinningVehicle.Value; public static bool AllowPinningPortal => _allowPinningPortal.Value; public static bool NotPinningTamedAnimals => _notPinningTamedAnimals.Value; public static float StaticObjectMappingInterval => _staticObjectMappingInterval.Value; public static float StaticObjectCachingInterval => _staticObjectCachingInterval.Value; public static bool SaveStaticObjectPins => _saveStaticObjectPins.Value; public static bool RemovePinsOfDestroyedObject => _removePinsOfDestroyedObject.Value; public static int FloraPinMergeRange => _floraPinMergeRange.Value; public static bool NeedToEquipWishboneForUndergroundMinerals => _needToEquipWishboneForUndergroundMinerals.Value; public static KeyboardShortcut StaticObjectMappingKey => _staticObjectMappingKey.Value; public static KeyboardShortcut NavigationStartKey => _navigationStartKey.Value; public static bool MappingPerformanceLog => _mappingPerformanceLog.Value; public static bool PinAnimalIncludesFish { get; private set; } public static bool PinAnimalIncludesBird { get; private set; } internal static event Action StaticAllowlistChanged; public static void Initialize() { //IL_0306: Unknown result type (might be due to invalid IL or missing references) //IL_030c: Unknown result type (might be due to invalid IL or missing references) //IL_0329: Unknown result type (might be due to invalid IL or missing references) Configuration instance = global::Automatics.Config.Instance; instance.ChangeSection("automatic_mapping"); _module = instance.Bind("module", AutomaticsModule.Enabled, null, delegate(ConfigurationManagerAttributes x) { x.DispName = Automatics.L10N.Translate("@config_common_disable_module_name"); x.Description = Automatics.L10N.Translate("@config_common_disable_module_description"); }); if (_module.Value != AutomaticsModule.Disabled) { _enableAutomaticMapping = instance.Bind("enable_automatic_mapping", defaultValue: true); _dynamicObjectMappingRange = instance.Bind("dynamic_object_mapping_range", 64, (0, 128)); _staticObjectMappingRange = instance.Bind("static_object_mapping_range", 32, (0, 128)); _locationMappingRange = instance.Bind("location_mapping_range", 96, (0, 128)); _allowPinningAnimal = instance.BindValheimObjectList("allow_pinning_animal", ValheimObject.Animal); _allowPinningMonster = instance.BindValheimObjectList("allow_pinning_monster", ValheimObject.Monster); _allowPinningFlora = instance.BindValheimObjectList("allow_pinning_flora", ValheimObject.Flora, null, new string[13] { "Raspberries", "Mushroom", "Blueberries", "CarrotSeeds", "Thistle", "TurnipSeeds", "Cloudberries", "JotunPuffs", "Magecap", "Fiddlehead", "SmokePuff", "Vineberry", "VineberrySeeds" }); _allowPinningMineral = instance.BindValheimObjectList("allow_pinning_mineral", ValheimObject.Mineral, null, null, new string[1] { "ObsidianDeposit" }); _allowPinningSpawner = instance.BindValheimObjectList("allow_pinning_spawner", ValheimObject.Spawner, Array.Empty()); _allowPinningVehicle = instance.BindValheimObjectList("allow_pinning_vehicle", MappingObject.Vehicle, null, new string[3] { "Karve", "Longship", "Drakkar" }); _allowPinningOther = instance.BindValheimObjectList("allow_pinning_other", MappingObject.Other, null, new string[1] { "WildBeehive" }); _allowPinningDungeon = instance.BindValheimObjectList("allow_pinning_dungeon", ValheimObject.Dungeon); _allowPinningSpot = instance.BindValheimObjectList("allow_pinning_spot", ValheimObject.Spot); _allowPinningPortal = instance.Bind("allow_pinning_portal", defaultValue: true); _notPinningTamedAnimals = instance.Bind("not_pinning_tamed_animals", defaultValue: true); _staticObjectMappingInterval = instance.Bind("static_object_mapping_interval", 0.25f, (0f, 4f)); _staticObjectCachingInterval = instance.Bind("static_object_caching_interval", 3, (1, 8)); _saveStaticObjectPins = instance.Bind("save_static_object_pins", defaultValue: false); _removePinsOfDestroyedObject = instance.Bind("remove_pins_of_destroyed_object", defaultValue: true); _floraPinMergeRange = instance.Bind("flora_pins_merge_range", 8, (0, 16)); _needToEquipWishboneForUndergroundMinerals = instance.Bind("need_to_equip_wishbone_for_underground_minerals", defaultValue: true); _staticObjectMappingKey = instance.Bind("static_object_mapping_key", default(KeyboardShortcut)); _navigationStartKey = instance.Bind("navigation_start_key", new KeyboardShortcut((KeyCode)304, Array.Empty())); _mappingPerformanceLog = instance.Bind("mapping_performance_log", defaultValue: false); RefreshAnimalListFlags(); _allowPinningAnimal.SettingChanged += delegate { RefreshAnimalListFlags(); }; _allowPinningFlora.SettingChanged += delegate { Config.StaticAllowlistChanged?.Invoke(ValheimObject.Flora); }; _allowPinningMineral.SettingChanged += delegate { Config.StaticAllowlistChanged?.Invoke(ValheimObject.Mineral); }; _allowPinningSpawner.SettingChanged += delegate { Config.StaticAllowlistChanged?.Invoke(ValheimObject.Spawner); }; _allowPinningOther.SettingChanged += delegate { Config.StaticAllowlistChanged?.Invoke(MappingObject.Other); }; _allowPinningDungeon.SettingChanged += delegate { Config.StaticAllowlistChanged?.Invoke(ValheimObject.Dungeon); }; _allowPinningSpot.SettingChanged += delegate { Config.StaticAllowlistChanged?.Invoke(ValheimObject.Spot); }; instance.ChangeSection("general", 128); instance.BindCustomValheimObject("custom_vehicle", MappingObject.Vehicle); instance.BindCustomValheimObject("custom_other", MappingObject.Other); } } private static void RefreshAnimalListFlags() { StringList stringList = _allowPinningAnimal?.Value; PinAnimalIncludesFish = stringList?.Contains("Fish") ?? false; PinAnimalIncludesBird = stringList?.Contains("Bird") ?? false; } } [DisallowMultipleComponent] internal class FloraNode : ObjectNode { private static readonly Dictionary NodeIndex = new Dictionary(); private Pickable _pickable; private ZNetView _zNetView; private ZDOID _uniqueId; private string Name { get { if (!Object.op_Implicit((Object)(object)_pickable)) { return string.Empty; } return Objects.GetName((Component)(object)_pickable); } } public Vector3 Position { get { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)_pickable)) { return Vector3.zero; } return ((Component)_pickable).transform.position; } } public ZDOID UniqueId => _uniqueId; protected override void Awake() { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) _pickable = ((Component)this).GetComponent(); _zNetView = ((Component)this).GetComponent(); _uniqueId = (((Object)(object)_zNetView != (Object)null && _zNetView.GetZDO() != null) ? _zNetView.GetZDO().m_uid : ZDOID.None); Destructible component = ((Component)_pickable).GetComponent(); if ((Object)(object)component != (Object)null) { component.m_onDestroyed = (Action)Delegate.Combine(component.m_onDestroyed, new Action(OnDestroyed)); } if (_uniqueId != ZDOID.None) { NodeIndex[_uniqueId] = this; } base.Awake(); } protected override void OnDestroy() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0055: 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_0030: Unknown result type (might be due to invalid IL or missing references) if (_uniqueId != ZDOID.None && NodeIndex.TryGetValue(_uniqueId, out var value) && value == this) { NodeIndex.Remove(_uniqueId); } base.OnDestroy(); _pickable = null; _zNetView = null; _uniqueId = ZDOID.None; } public static FloraNode Find(ZDOID uniqueId) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) if (!(uniqueId != ZDOID.None) || !NodeIndex.TryGetValue(uniqueId, out var value) || !value.IsValid()) { return null; } return value; } private void OnDestroyed() { base.Network?.RemoveNode(this); } protected override FloraNetwork CreateNetwork() { return new FloraNetwork(); } protected override bool IsConnectable(FloraNode other) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) if (Vector3.Distance(Position, other.Position) <= (float)Config.FloraPinMergeRange) { return Name == other.Name; } return false; } public bool IsValid() { if (Object.op_Implicit((Object)(object)_pickable) && Object.op_Implicit((Object)(object)_zNetView)) { return _zNetView.GetZDO() != null; } return false; } } internal class FloraNetwork : ObjectNetwork { public Vector3 Center { get; private set; } public FloraNetwork() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) Center = Vector3.zero; base.OnNodeChanged = (Action>)Delegate.Combine(base.OnNodeChanged, (Action>)delegate(IEnumerable nodes) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: 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_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) int num = 0; Vector3 val = Vector3.zero; foreach (FloraNode item in nodes.Where((FloraNode x) => x.IsValid())) { val += item.Position; num++; } Center = ((num > 0) ? (val / (float)num) : Vector3.zero); }); } public void FillValidNodes(List buffer) { if (buffer == null) { throw new ArgumentNullException("buffer"); } buffer.Clear(); foreach (FloraNode item in EnumerateNodes()) { if ((Object)(object)item != (Object)null && item.IsValid()) { buffer.Add(item); } } } } internal static class MappingObject { public static ValheimObject Vehicle { get; } = new ValheimObject("vehicle"); public static ValheimObject Other { get; } = new ValheimObject("other"); } [DisallowMultipleComponent] public sealed class FishCache : InstanceCache { } [DisallowMultipleComponent] public sealed class BirdCache : InstanceCache { } [DisallowMultipleComponent] public sealed class ShipCache : InstanceCache { } [DisallowMultipleComponent] internal sealed class MineRock5CacheBinding : MonoBehaviour { private MineRock5 _rock; public void Initialize(MineRock5 rock) { _rock = rock; MineRock5Cache.Register(rock); } private void OnDestroy() { MineRock5Cache.Unregister(_rock); _rock = null; } } internal static class IconPack { private class Icon { public Target Target; public PinType PinType = (PinType)3; public Options Options; } private static readonly List Icons; private static readonly List OverridablePins; private static PinType _vanillaPinTypeLength; static IconPack() { Icons = new List(); OverridablePins = new List { (PinType)0, (PinType)1, (PinType)2, (PinType)3, (PinType)6 }; } [UsedImplicitly] public static float ResizeIcon(PinData pinData, float originalSize) { //IL_003a: 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_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Expected I4, but got Unknown Icon icon = Icons.FirstOrDefault((Icon x) => x.PinType == pinData.m_type); if (icon == null) { return originalSize; } Options options = icon.Options; if (options == null) { return originalSize; } MapMode mode = Minimap.instance.m_mode; switch ((int)mode) { case 2: if (!(options.iconScaleLargeMap > 0f)) { return originalSize; } return originalSize * options.iconScaleLargeMap; case 1: if (!(options.iconScaleSmallMap > 0f)) { return originalSize; } return originalSize * options.iconScaleSmallMap; default: throw new ArgumentOutOfRangeException(); case 0: return originalSize; } } [UsedImplicitly] public static bool IsNameTagHidden(PinData pinData) { //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) if (pinData.m_type <= _vanillaPinTypeLength) { return false; } Icon icon = Icons.FirstOrDefault((Icon x) => x.PinType == pinData.m_type); if (icon?.Options != null) { return icon.Options.hideNameTag; } return false; } public static PinType GetPinType(Target target) { //IL_00fa: Unknown result type (might be due to invalid IL or missing references) if (!Icons.Any()) { return (PinType)3; } string internalName = target.name; string displayName = Automatics.L10N.TranslateInternalName(internalName); string prefabName = target.prefabName; MetaData meta = target.metadata; return (from x in Icons let data = x.Target where (string.IsNullOrEmpty(data.name) || (L10N.IsInternalName(data.name) ? IsNameMatch(internalName, data.name, exactMatch: true) : IsNameMatch(displayName, data.name, exactMatch: false))) && (string.IsNullOrEmpty(data.prefabName) || IsNameMatch(prefabName, data.prefabName, exactMatch: true)) && (data.metadata == null || IsMetaDataEquals(data.metadata, meta)) orderby data.metadata != null descending, data.metadata select GetPinType(x)).DefaultIfEmpty((PinType)3).FirstOrDefault(); } private static PinType GetPinType(Icon icon) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Invalid comparison between Unknown and I4 //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: 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_0033: Unknown result type (might be due to invalid IL or missing references) if ((int)icon.PinType > 13 || icon.Options == null) { return icon.PinType; } PinType val = (PinType)icon.Options.defaultIconOverride; if (!OverridablePins.Contains(val)) { return icon.PinType; } return val; } private static bool IsNameMatch(string name, string pattern, bool exactMatch) { if (pattern.StartsWith("r/", StringComparison.OrdinalIgnoreCase)) { return Regex.IsMatch(name, pattern.Substring(2)); } if (!exactMatch) { return name.IndexOf(pattern, StringComparison.OrdinalIgnoreCase) >= 0; } return name.Equals(pattern, StringComparison.Ordinal); } private static bool IsMetaDataEquals(MetaData a, MetaData b) { if (a != null) { return a.CompareTo(b) == 0; } return false; } public static void Initialize() { //IL_0019: Unknown result type (might be due to invalid IL or missing references) _vanillaPinTypeLength = (PinType)Enum.GetValues(typeof(PinType)).OfType().Count(); Icons.Clear(); List<(Icon, Sprite)> sprites = new List<(Icon, Sprite)>(); foreach (string item in Automatics.GetAllResourcePath("Textures")) { LoadIcons(item, sprites); } RegisterIcons(sprites); } private static void LoadIcons(string directory, List<(Icon, Sprite)> sprites) { if (string.IsNullOrEmpty(directory)) { return; } string text = Path.Combine(directory, "custom-map-icon.json"); if (!File.Exists(text)) { return; } try { Automatics.Logger.Info("Load icon data from " + text); SpriteLoader spriteLoader = new SpriteLoader(); spriteLoader.SetDebugLogger(Automatics.Logger); foreach (IconPackEntry entry in Json.Parse>(File.ReadAllText(text))) { Icon icon = new Icon { Target = entry.target, Options = entry.options }; if (string.IsNullOrEmpty(entry.target.name) && string.IsNullOrEmpty(entry.target.prefabName)) { Automatics.Logger.Warning("Both target.name and target.prefabName cannot be omitted."); continue; } if (entry.sprite != null) { SpriteInfo sprite = entry.sprite; string texturePath = Path.Combine(directory, sprite.file); Sprite val = spriteLoader.Load(texturePath, sprite.width, sprite.height); if ((Object)(object)val == (Object)null) { continue; } sprites.Add((icon, val)); } else { Options options = entry.options; if (options == null) { Automatics.Logger.Warning("Both sprite and options cannot be omitted."); continue; } if (options.defaultIconOverride == -1) { Automatics.Logger.Warning("If sprite is omitted, options.defaultIconOverride must be set."); continue; } if (!OverridablePins.Contains((PinType)options.defaultIconOverride)) { Automatics.Logger.Warning($"{options.defaultIconOverride} is an icon that does not support override."); continue; } if (options.hideNameTag) { Automatics.Logger.Warning("If sprite is omitted, options.hideNameTag cannot be set."); continue; } } Icons.Add(icon); Automatics.Logger.Info(delegate { string text2 = entry.target.name; if (string.IsNullOrEmpty(text2)) { text2 = entry.target.prefabName; } return "* Loaded icon data for " + text2; }); } } catch (Exception arg) { Automatics.Logger.Error($"Failed to load icon data: {text}\n{arg}"); } } private static void RegisterIcons(List<(Icon, Sprite)> sprites) { //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) if (sprites.Any()) { Minimap instance = Minimap.instance; bool[] field = Reflections.GetField(instance, "m_visibleIconTypes"); int num = field.Length; bool[] array = new bool[num + sprites.Count]; for (int i = 0; i < array.Length; i++) { array[i] = i < num && field[i]; } Reflections.SetField(instance, "m_visibleIconTypes", array); Automatics.Logger.Info($"Minimap.m_visibleIconTypes Expanded: {num} -> {array.Length}"); for (int j = 0; j < sprites.Count; j++) { (Icon, Sprite) tuple = sprites[j]; Icon item = tuple.Item1; Sprite item2 = tuple.Item2; PinType val = (item.PinType = (PinType)(num + j)); instance.m_icons.Add(new SpriteData { m_name = val, m_icon = item2 }); Automatics.Logger.Info($"Register new sprite data: ({val}, {SpriteLoader.GetTextureFileName(item2)})"); } } } } [Serializable] public struct IconPackEntry { public Target target; public SpriteInfo sprite; public Options options; } [Serializable] public struct Target { public string name; public string prefabName; public MetaData metadata; } [Serializable] public class MetaData : IComparable { public int level = -1; public int CompareTo(MetaData other) { if (this == other) { return 0; } if (other == null) { return 1; } return level.CompareTo(other.level); } } [Serializable] public class SpriteInfo { public string file; public int width; public int height; } [Serializable] public class Options { public int defaultIconOverride = -1; public bool hideNameTag; public float iconScaleLargeMap; public float iconScaleSmallMap; } internal static class Map { private static FieldRef> _pinsRef; private static Action _updatePinsInvoker; private static readonly List EmptyPinList = new List(); private static Minimap ValheimMap => Minimap.instance; public static void OnMinimapStart() { if (_pinsRef == null) { try { _pinsRef = AccessTools.FieldRefAccess>("m_pins"); } catch (Exception ex) { Exception ex2 = ex; Exception e2 = ex2; Automatics.Logger.Warning(() => "Failed to bind Minimap.m_pins field ref; falling back to reflection: " + e2.Message); _pinsRef = null; } } if (_updatePinsInvoker == null) { try { MethodInfo methodInfo = AccessTools.Method(typeof(Minimap), "UpdatePins", (Type[])null, (Type[])null); _updatePinsInvoker = ((methodInfo != null) ? AccessTools.MethodDelegate>(methodInfo, (object)null, true) : null); if (_updatePinsInvoker == null) { Automatics.Logger.Warning(() => "Minimap.UpdatePins not found; falling back to reflection."); } } catch (Exception ex3) { Exception ex2 = ex3; Exception e = ex2; Automatics.Logger.Warning(() => "Failed to bind Minimap.UpdatePins delegate; falling back to reflection: " + e.Message); _updatePinsInvoker = null; } } PinIndex.Clear(); List allPins = GetAllPins(); for (int i = 0; i < allPins.Count; i++) { PinIndex.Track(allPins[i]); } } public static List GetAllPins() { Minimap valheimMap = ValheimMap; if (!Object.op_Implicit((Object)(object)valheimMap)) { return EmptyPinList; } if (_pinsRef == null) { return FallbackGetAllPins(valheimMap); } return _pinsRef.Invoke(valheimMap); } private static List FallbackGetAllPins(Minimap map) { return Reflections.GetField>(map, "m_pins") ?? EmptyPinList; } private static void DestroyPinMarker(PinData pinData) { Reflections.InvokeMethod(ValheimMap, "DestroyPinMarker", pinData); } private static bool IsActive(PinData pinData) { if (Object.op_Implicit((Object)(object)pinData.m_uiElement)) { return ((Component)pinData.m_uiElement).gameObject.activeInHierarchy; } return false; } public static PinData GetClosestPin(Vector3 pos, float radius = 1f, Predicate predicate = null) { //IL_0013: 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_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) using (MappingProfiler.BeginScope(4)) { float num = radius * radius; PinData result = null; float num2 = float.MaxValue; int num3 = Mathf.FloorToInt((pos.x - radius) / 32f); int num4 = Mathf.FloorToInt((pos.x + radius) / 32f); int num5 = Mathf.FloorToInt((pos.z - radius) / 32f); int num6 = Mathf.FloorToInt((pos.z + radius) / 32f); for (int i = num3; i <= num4; i++) { for (int j = num5; j <= num6; j++) { if (!PinIndex.TryGetCell(new CellKey(i, j), out var pins)) { continue; } for (int k = 0; k < pins.Count; k++) { PinData val = pins[k]; if (IsActive(val)) { float num7 = pos.x - val.m_pos.x; float num8 = pos.z - val.m_pos.z; float num9 = num7 * num7 + num8 * num8; if (!(num9 > num) && !(num9 >= num2) && (predicate == null || predicate(val))) { result = val; num2 = num9; } } } } } IReadOnlyList transientPins = PinIndex.TransientPins; for (int l = 0; l < transientPins.Count; l++) { PinData val2 = transientPins[l]; if (IsActive(val2)) { float num10 = pos.x - val2.m_pos.x; float num11 = pos.z - val2.m_pos.z; float num12 = num10 * num10 + num11 * num11; if (!(num12 > num) && !(num12 >= num2) && (predicate == null || predicate(val2))) { result = val2; num2 = num12; } } } return result; } } public static bool HavePinInRange(Vector3 pos, float radius, Predicate predicate = null) { //IL_0004: 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_002b: 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_011c: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) float num = radius * radius; int num2 = Mathf.FloorToInt((pos.x - radius) / 32f); int num3 = Mathf.FloorToInt((pos.x + radius) / 32f); int num4 = Mathf.FloorToInt((pos.z - radius) / 32f); int num5 = Mathf.FloorToInt((pos.z + radius) / 32f); for (int i = num2; i <= num3; i++) { for (int j = num4; j <= num5; j++) { if (!PinIndex.TryGetCell(new CellKey(i, j), out var pins)) { continue; } for (int k = 0; k < pins.Count; k++) { PinData val = pins[k]; if (IsActive(val)) { float num6 = pos.x - val.m_pos.x; float num7 = pos.z - val.m_pos.z; if (!(num6 * num6 + num7 * num7 > num) && (predicate == null || predicate(val))) { return true; } } } } } IReadOnlyList transientPins = PinIndex.TransientPins; for (int l = 0; l < transientPins.Count; l++) { PinData val2 = transientPins[l]; if (IsActive(val2)) { float num8 = pos.x - val2.m_pos.x; float num9 = pos.z - val2.m_pos.z; if (!(num8 * num8 + num9 * num9 > num) && (predicate == null || predicate(val2))) { return true; } } } return false; } public static PinData AddPin(Vector3 pos, string name, bool save, Target target) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) return AddPin(pos, IconPack.GetPinType(target), name, save); } public static bool ContainsPin(PinData pinData) { return PinIndex.Contains(pinData); } public static void MovePin(PinData pinData, Vector3 newPosition) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) if (pinData != null) { PinIndex.Move(pinData, newPosition); pinData.m_pos = newPosition; } } public static void RefreshPins() { using (MappingProfiler.BeginScope(5)) { Minimap valheimMap = ValheimMap; if (Object.op_Implicit((Object)(object)valheimMap)) { if (_updatePinsInvoker != null) { _updatePinsInvoker(valheimMap); } else { Reflections.InvokeMethod(valheimMap, "UpdatePins"); } } } } private static string EscapePinName(string name) { return name.Replace("\n", ""); } private static PinData AddPin(Vector3 pos, PinType type, string name, bool save) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: 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_004a: 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_0061: Unknown result type (might be due to invalid IL or missing references) if (name.StartsWith("@")) { name = "$automatics_" + name.Substring(1); } PinData pinData = ValheimMap.AddPin(pos, type, name, save, false, 0L, default(PlatformUserID)); Automatics.Logger.Debug(() => $"Add pin: [name: {EscapePinName(name)}, pos: {pinData.m_pos}, icon: {(int)type}]"); return pinData; } public static PinData RemovePin(PinData pinData) { if (pinData == null) { return null; } if (Object.op_Implicit((Object)(object)pinData.m_uiElement)) { DestroyPinMarker(pinData); } if (!GetAllPins().Remove(pinData)) { return null; } Automatics.Logger.Debug(() => $"Remove pin: [name: {EscapePinName(pinData.m_name)}, pos: {pinData.m_pos}, icon: {(int)pinData.m_type}]"); AutomaticMapping.OnRemovePin(pinData); return pinData; } public static PinData RemovePin(Vector3 pos, float radius = 1f, Predicate predicate = null) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) if (predicate == null) { predicate = (PinData x) => x.m_save; } PinData closestPin = GetClosestPin(pos, radius, predicate); if (closestPin == null) { return null; } return RemovePin(closestPin); } } internal static class MappingProfiler { public readonly struct Scope : IDisposable { private readonly int _slot; private readonly long _start; internal Scope(int slot, long start) { _slot = slot; _start = start; } public void Dispose() { if (_start != 0L) { Accumulate(_slot, Stopwatch.GetTimestamp() - _start); } } } public const int SlotDynamicMapping = 0; public const int SlotStaticMapping = 1; public const int SlotCacheStaticObjects = 2; public const int SlotAnimatePins = 3; public const int SlotGetClosestPin = 4; public const int SlotRefreshPins = 5; private const int SlotCount = 6; private const double FlushIntervalSeconds = 1.0; private static readonly string[] SlotNames = new string[6] { "DynamicMapping", "StaticMapping", "CacheStaticObjects", "AnimatePins", "GetClosestPin", "RefreshPins" }; private static readonly long[] ElapsedTicks = new long[6]; private static readonly long[] CallCount = new long[6]; private static long _flushAnchor; public static bool IsEnabled => Config.MappingPerformanceLog; public static Scope BeginScope(int slot) { return new Scope(slot, IsEnabled ? Stopwatch.GetTimestamp() : 0); } public static void FlushIfDue() { if (!IsEnabled) { return; } long timestamp = Stopwatch.GetTimestamp(); if (_flushAnchor == 0L) { _flushAnchor = timestamp; } else { if ((double)(timestamp - _flushAnchor) / (double)Stopwatch.Frequency < 1.0) { return; } _flushAnchor = timestamp; StringBuilder stringBuilder = new StringBuilder("[MappingProfiler] "); bool flag = false; for (int i = 0; i < 6; i++) { long num = Interlocked.Exchange(ref ElapsedTicks[i], 0L); long num2 = Interlocked.Exchange(ref CallCount[i], 0L); if (num2 != 0L) { if (flag) { stringBuilder.Append(' '); } flag = true; double num3 = (double)num * 1000.0 / (double)Stopwatch.Frequency; double num4 = (double)num * 1000000.0 / (double)Stopwatch.Frequency / (double)num2; stringBuilder.Append(SlotNames[i]).Append('=').Append(num3.ToString("F2")) .Append("ms/") .Append(num2) .Append("x(avg ") .Append(num4.ToString("F1")) .Append("us)"); } } if (flag) { Automatics.LogSource.Log((LogLevel)16, (object)stringBuilder.ToString()); } } } public static void Reset() { for (int i = 0; i < 6; i++) { Interlocked.Exchange(ref ElapsedTicks[i], 0L); Interlocked.Exchange(ref CallCount[i], 0L); } _flushAnchor = 0L; } private static void Accumulate(int slot, long elapsed) { Interlocked.Add(ref ElapsedTicks[slot], elapsed); Interlocked.Increment(ref CallCount[slot]); } } internal static class MineRock5Cache { internal readonly struct Snapshot { public readonly Collider[] Colliders; public readonly Vector3 Center; public readonly float MaxHeight; public int ColliderCount { get { if (Colliders == null) { return 0; } return Colliders.Length; } } public Snapshot(Collider[] colliders, Vector3 center, float maxHeight) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) Colliders = colliders; Center = center; MaxHeight = maxHeight; } } private static readonly Collider[] EmptyColliders = Array.Empty(); private static readonly Snapshot EmptySnapshot = new Snapshot(EmptyColliders, Vector3.zero, float.MinValue); private static readonly Dictionary Snapshots = new Dictionary(); private static Func _nonDestroyed; private static bool _delegateInitialized; public static void InitializeDelegate() { if (_delegateInitialized) { return; } _delegateInitialized = true; try { MethodInfo methodInfo = AccessTools.DeclaredMethod(typeof(MineRock5), "NonDestroyed", (Type[])null, (Type[])null); _nonDestroyed = ((methodInfo != null) ? AccessTools.MethodDelegate>(methodInfo, (object)null, true) : null); if (_nonDestroyed == null) { Automatics.Logger.Warning(() => "MineRock5.NonDestroyed not found; falling back to reflection."); } } catch (Exception ex) { Exception ex2 = ex; Exception e = ex2; Automatics.Logger.Warning(() => "Failed to bind MineRock5.NonDestroyed delegate; falling back to reflection: " + e.Message); _nonDestroyed = null; } } public static bool IsAlive(MineRock5 rock5) { if (!Object.op_Implicit((Object)(object)rock5)) { return false; } if (_nonDestroyed == null) { return Reflections.InvokeMethod(rock5, "NonDestroyed"); } return _nonDestroyed(rock5); } public static void Register(MineRock5 rock5) { if (Object.op_Implicit((Object)(object)rock5)) { Snapshots[rock5] = BuildSnapshot(rock5); } } public static void Unregister(MineRock5 rock5) { if (rock5 != null) { Snapshots.Remove(rock5); } } public static bool TryGetSnapshot(MineRock5 rock5, out Snapshot snapshot) { if (!Object.op_Implicit((Object)(object)rock5)) { snapshot = EmptySnapshot; return false; } return Snapshots.TryGetValue(rock5, out snapshot); } public static bool TryGetOrBuildSnapshotAlive(MineRock5 rock5, out Snapshot snapshot) { if (!Object.op_Implicit((Object)(object)rock5)) { snapshot = EmptySnapshot; return false; } if (Snapshots.TryGetValue(rock5, out snapshot)) { if (IsAlive(rock5)) { return true; } Snapshots.Remove(rock5); snapshot = EmptySnapshot; return false; } if (!IsAlive(rock5)) { snapshot = EmptySnapshot; return false; } snapshot = BuildSnapshot(rock5); Snapshots[rock5] = snapshot; return true; } public static void Clear() { Snapshots.Clear(); } private static Snapshot BuildSnapshot(MineRock5 rock5) { //IL_002e: 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_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: 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_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0055: 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_007d: 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_0067: Unknown result type (might be due to invalid IL or missing references) Collider[] array = ((Component)rock5).gameObject.GetComponentsInChildren() ?? EmptyColliders; if (array.Length == 0) { return new Snapshot(EmptyColliders, Vector3.zero, float.MinValue); } Vector3 val = Vector3.zero; float num = float.MinValue; for (int i = 0; i < array.Length; i++) { Bounds bounds = array[i].bounds; val += ((Bounds)(ref bounds)).center; if (((Bounds)(ref bounds)).max.y > num) { num = ((Bounds)(ref bounds)).max.y; } } return new Snapshot(array, val / (float)array.Length, num); } } internal static class Module { [AutomaticsInitializer(2)] private static void Initialize() { Config.Initialize(); if (Config.ModuleDisabled) { return; } MineRock5Cache.InitializeDelegate(); InstanceCache.OnCacheAdded = (Action)Delegate.Combine(InstanceCache.OnCacheAdded, (Action)delegate(Pickable pickable) { if (ValheimObject.Flora.IsDefined(Objects.GetName((Component)(object)pickable))) { ((Component)pickable).gameObject.AddComponent(); } }); InstanceCache.OnCacheAdded = (Action)Delegate.Combine(InstanceCache.OnCacheAdded, (Action)delegate(Piece ship) { WearNTear component = ((Component)ship).GetComponent(); if (Object.op_Implicit((Object)(object)component)) { component.m_onDestroyed = (Action)Delegate.Combine(component.m_onDestroyed, (Action)delegate { DynamicObjectMapping.OnObjectDestroy((Component)(object)ship); }); } }); Hooks.OnPlayerAwake = (Action)Delegate.Combine(Hooks.OnPlayerAwake, (Action)delegate(Player player, ZNetView zNetView) { if ((Object)(object)Player.m_localPlayer == (Object)(object)player) { AutomaticMapping.Cleanup(); } }); Hooks.OnPlayerUpdate = (Action)Delegate.Combine(Hooks.OnPlayerUpdate, (Action)delegate(Player player, bool takeInput) { Navigation.Update(player); }); Hooks.OnPlayerFixedUpdate = (Action)Delegate.Combine(Hooks.OnPlayerFixedUpdate, new Action(AutomaticMapping.DynamicMapping)); string harmonyId = Automatics.GetHarmonyId("automatic-mapping"); Harmony.CreateAndPatchAll(typeof(Patches), harmonyId); Harmony.CreateAndPatchAll(typeof(Patches.RandomFlyingBird_Initialize_Patch), harmonyId); Harmony.CreateAndPatchAll(typeof(Patches.Minimap_OnDestroy_Patch), harmonyId); } } internal static class Navigation { private const float TargetPinValidationInterval = 0.5f; private const float OverlayMinWidth = 120f; private const float OverlayHeight = 44f; private const float EdgeMargin = 40f; private const float TextLeft = 8f; private const float TextRight = 8f; private const float TextHeight = 18f; private static PinData _targetPin; private static GameObject _overlayObject; private static RectTransform _overlayRect; private static Text _nameText; private static Text _distanceText; private static string _displayName = string.Empty; private static string _displayDistance = string.Empty; private static bool _overlayWidthDirty; private static float _nextTargetPinValidationTime; public static void Cleanup() { _targetPin = null; _displayName = string.Empty; _displayDistance = string.Empty; _overlayWidthDirty = false; _nextTargetPinValidationTime = 0f; DestroyOverlay(); } public static void OnRemovePin(PinData pinData) { if (pinData != null && pinData == _targetPin) { ClearTarget(showMessage: false); } } public static bool TryHandleMapClick(Minimap map) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0012: 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_0022: Invalid comparison between Unknown and I4 //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)map)) { return false; } KeyboardShortcut navigationStartKey = Config.NavigationStartKey; if ((int)((KeyboardShortcut)(ref navigationStartKey)).MainKey == 0) { return false; } if ((int)map.m_mode != 2) { return false; } navigationStartKey = Config.NavigationStartKey; if (!((KeyboardShortcut)(ref navigationStartKey)).IsPressed()) { return false; } Vector3 pos = Reflections.InvokeMethod(map, "ScreenToWorldPoint", new object[1] { ZInput.mousePosition }); float field = Reflections.GetField(map, "m_removeRadius"); float field2 = Reflections.GetField(map, "m_largeZoom"); float radius = field * (field2 * 2f); PinData closestPin = Map.GetClosestPin(pos, radius); if (closestPin == null) { return false; } if (closestPin == _targetPin) { ClearTarget(showMessage: true); } else { SetTarget(closestPin); } return true; } public static void Update(Player player) { //IL_0021: 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_0027: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) ValidateTargetPin(); if (!ShouldShow(player)) { SetVisible(visible: false); } else { if (!EnsureOverlay()) { return; } Vector3 pos = _targetPin.m_pos; if (!TryGetScreenPoint(pos, out var screenPoint)) { SetVisible(visible: false); return; } UpdateName(); UpdateDistance(player, pos); if (_overlayWidthDirty) { ResizeOverlay(); } UpdatePosition(screenPoint); SetVisible(visible: true); } } private static bool ShouldShow(Player player) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Invalid comparison between Unknown and I4 if (_targetPin != null && Object.op_Implicit((Object)(object)player) && (Object)(object)player == (Object)(object)Player.m_localPlayer && ((Character)player).IsOwner() && !Game.IsPaused() && Object.op_Implicit((Object)(object)Hud.instance) && Object.op_Implicit((Object)(object)Minimap.instance)) { return (int)Minimap.instance.m_mode != 2; } return false; } private static void SetTarget(PinData pinData) { _targetPin = pinData; _displayName = string.Empty; _displayDistance = string.Empty; _overlayWidthDirty = true; _nextTargetPinValidationTime = 0f; ShowStartMessage(pinData); } private static void ClearTarget(bool showMessage) { _targetPin = null; _displayName = string.Empty; _displayDistance = string.Empty; _overlayWidthDirty = false; _nextTargetPinValidationTime = 0f; SetVisible(visible: false); if (showMessage) { ShowMessage(Automatics.L10N.Localize("@message_automatic_mapping_navigation_cleared")); } } private static void SetVisible(bool visible) { if (Object.op_Implicit((Object)(object)_overlayObject)) { _overlayObject.SetActive(visible); } } private static bool EnsureOverlay() { //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Expected O, but got Unknown //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: 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) if (Object.op_Implicit((Object)(object)_overlayObject) && Object.op_Implicit((Object)(object)_overlayRect) && Object.op_Implicit((Object)(object)_nameText) && Object.op_Implicit((Object)(object)_distanceText)) { return true; } DestroyOverlay(); RectTransform overlayParent = GetOverlayParent(); if (!Object.op_Implicit((Object)(object)overlayParent)) { return false; } _overlayObject = new GameObject("AutomaticsNavigationOverlay", new Type[3] { typeof(RectTransform), typeof(CanvasRenderer), typeof(Image) }); _overlayRect = _overlayObject.GetComponent(); ((Transform)_overlayRect).SetParent((Transform)(object)overlayParent, false); _overlayRect.anchorMin = new Vector2(0.5f, 0.5f); _overlayRect.anchorMax = new Vector2(0.5f, 0.5f); _overlayRect.pivot = new Vector2(0.5f, 0.5f); _overlayRect.sizeDelta = new Vector2(120f, 44f); ((Transform)_overlayRect).SetAsLastSibling(); Image component = _overlayObject.GetComponent(); ((Graphic)component).color = new Color(0f, 0f, 0f, 0.45f); ((Graphic)component).raycastTarget = false; _nameText = CreateNameText((Transform)(object)_overlayRect); _distanceText = CreateDistanceText((Transform)(object)_overlayRect); SetVisible(visible: false); return true; } private static RectTransform GetOverlayParent() { if (!Object.op_Implicit((Object)(object)Hud.instance)) { return null; } Transform transform = ((Component)Hud.instance).transform; RectTransform val = (RectTransform)(object)((transform is RectTransform) ? transform : null); if (Object.op_Implicit((Object)(object)val)) { return val; } Canvas componentInChildren = ((Component)Hud.instance).GetComponentInChildren(); if (!Object.op_Implicit((Object)(object)componentInChildren)) { return null; } Transform transform2 = ((Component)componentInChildren).transform; return (RectTransform)(object)((transform2 is RectTransform) ? transform2 : null); } private static Text CreateDistanceText(Transform parent) { //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Expected O, but got Unknown //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_009d: 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_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("Distance", new Type[4] { typeof(RectTransform), typeof(CanvasRenderer), typeof(Text), typeof(Outline) }); RectTransform component = val.GetComponent(); ((Transform)component).SetParent(parent, false); component.anchorMin = new Vector2(0f, 0.5f); component.anchorMax = new Vector2(1f, 0.5f); component.pivot = new Vector2(0f, 0.5f); component.anchoredPosition = new Vector2(8f, -10f); component.sizeDelta = new Vector2(-16f, 18f); Text component2 = val.GetComponent(); component2.font = Resources.GetBuiltinResource("Arial.ttf"); component2.fontSize = 14; component2.fontStyle = (FontStyle)1; component2.alignment = (TextAnchor)3; ((Graphic)component2).color = Color.white; component2.horizontalOverflow = (HorizontalWrapMode)1; component2.verticalOverflow = (VerticalWrapMode)1; ((Graphic)component2).raycastTarget = false; Outline component3 = val.GetComponent(); ((Shadow)component3).effectColor = new Color(0f, 0f, 0f, 0.9f); ((Shadow)component3).effectDistance = new Vector2(1f, -1f); return component2; } private static Text CreateNameText(Transform parent) { //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Expected O, but got Unknown //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_009d: 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_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("Name", new Type[4] { typeof(RectTransform), typeof(CanvasRenderer), typeof(Text), typeof(Outline) }); RectTransform component = val.GetComponent(); ((Transform)component).SetParent(parent, false); component.anchorMin = new Vector2(0f, 0.5f); component.anchorMax = new Vector2(1f, 0.5f); component.pivot = new Vector2(0f, 0.5f); component.anchoredPosition = new Vector2(8f, 10f); component.sizeDelta = new Vector2(-16f, 18f); Text component2 = val.GetComponent(); component2.font = Resources.GetBuiltinResource("Arial.ttf"); component2.fontSize = 14; component2.fontStyle = (FontStyle)1; component2.alignment = (TextAnchor)3; ((Graphic)component2).color = Color.white; component2.horizontalOverflow = (HorizontalWrapMode)1; component2.verticalOverflow = (VerticalWrapMode)1; ((Graphic)component2).raycastTarget = false; Outline component3 = val.GetComponent(); ((Shadow)component3).effectColor = new Color(0f, 0f, 0f, 0.9f); ((Shadow)component3).effectDistance = new Vector2(1f, -1f); return component2; } private static void UpdateName() { string displayPinName = GetDisplayPinName(_targetPin); if (!(_displayName == displayPinName)) { _displayName = displayPinName; _nameText.text = displayPinName; _overlayWidthDirty = true; } } private static void UpdateDistance(Player player, Vector3 targetPos) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) string text = $"{Mathf.RoundToInt(Utils.DistanceXZ(((Component)player).transform.position, targetPos))}m"; if (!(_displayDistance == text)) { _displayDistance = text; _distanceText.text = text; _overlayWidthDirty = true; } } private static void UpdatePosition(Vector2 screenPoint) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_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_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006b: 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_0086: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) Transform parent = ((Transform)_overlayRect).parent; RectTransform val = (RectTransform)(object)((parent is RectTransform) ? parent : null); if (Object.op_Implicit((Object)(object)val)) { Canvas componentInParent = ((Component)_overlayRect).GetComponentInParent(); Camera val2 = (((Object)(object)componentInParent != (Object)null && (int)componentInParent.renderMode != 0) ? componentInParent.worldCamera : null); Vector2 val3 = default(Vector2); if (RectTransformUtility.ScreenPointToLocalPointInRectangle(val, screenPoint, val2, ref val3)) { Rect rect = val.rect; float num = ((Rect)(ref rect)).width * 0.5f; rect = val.rect; float num2 = ((Rect)(ref rect)).height * 0.5f; rect = _overlayRect.rect; float num3 = ((Rect)(ref rect)).width * 0.5f; rect = _overlayRect.rect; float num4 = ((Rect)(ref rect)).height * 0.5f; float num5 = Mathf.Max(0f, num - num3 - 40f); float num6 = Mathf.Max(0f, num2 - num4 - 40f); val3.x = Mathf.Clamp(val3.x, 0f - num5, num5); val3.y = Mathf.Clamp(val3.y, 0f - num6, num6); _overlayRect.anchoredPosition = val3; } } } private static bool TryGetScreenPoint(Vector3 targetPos, out Vector2 screenPoint) { //IL_0001: 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_0019: 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_001f: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) screenPoint = default(Vector2); Camera worldCamera = GetWorldCamera(); if (!Object.op_Implicit((Object)(object)worldCamera)) { return false; } Vector3 val = worldCamera.WorldToViewportPoint(targetPos); if (val.z <= 0f) { return false; } if (val.x < 0f || val.x > 1f) { return false; } if (val.y < 0f || val.y > 1f) { return false; } float num = (((float)Screen.width <= 0f) ? 0f : (40f / (float)Screen.width)); float num2 = (((float)Screen.height <= 0f) ? 0f : (40f / (float)Screen.height)); val.x = Mathf.Clamp(val.x, num, 1f - num); val.y = Mathf.Clamp(val.y, num2, 1f - num2); screenPoint = new Vector2(val.x * (float)Screen.width, val.y * (float)Screen.height); return true; } private static Camera GetWorldCamera() { if (Object.op_Implicit((Object)(object)GameCamera.instance)) { Camera field = Reflections.GetField(GameCamera.instance, "m_camera"); if (Object.op_Implicit((Object)(object)field)) { return field; } } return Camera.main; } private static void DestroyOverlay() { if (Object.op_Implicit((Object)(object)_overlayObject)) { Object.Destroy((Object)(object)_overlayObject); } _overlayObject = null; _overlayRect = null; _nameText = null; _distanceText = null; } private static void ShowStartMessage(PinData pinData) { string displayPinName = GetDisplayPinName(pinData); ShowMessage(string.IsNullOrEmpty(displayPinName) ? Automatics.L10N.Localize("@message_automatic_mapping_navigation_started") : Automatics.L10N.Localize("@message_automatic_mapping_navigation_started_to", displayPinName)); } private static void ShowMessage(string message) { Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)2, message, 0, (Sprite)null); } } private static void ResizeOverlay() { //IL_005c: Unknown result type (might be due to invalid IL or missing references) float num = Mathf.Max(_nameText.preferredWidth, _distanceText.preferredWidth); float num2 = Mathf.Max(120f, 16f + num); if (Screen.width > 0) { num2 = Mathf.Min(num2, Mathf.Max(120f, (float)Screen.width - 80f)); } _overlayRect.sizeDelta = new Vector2(num2, 44f); _overlayWidthDirty = false; } private static void ValidateTargetPin() { if (_targetPin != null && !(Time.time < _nextTargetPinValidationTime)) { _nextTargetPinValidationTime = Time.time + 0.5f; if (!Map.ContainsPin(_targetPin)) { ClearTarget(showMessage: false); } } } private static string GetDisplayPinName(PinData pinData) { string text = pinData?.m_name; if (string.IsNullOrEmpty(text)) { return string.Empty; } text = text.Replace("\n", " ").Trim(); if (Localization.instance == null) { return text; } return Localization.instance.Localize(text); } } [HarmonyPatch] internal static class Patches { [HarmonyPatch] internal static class RandomFlyingBird_Initialize_Patch { [HarmonyTargetMethod] private static MethodBase TargetMethod() { return AccessTools.DeclaredMethod(typeof(RandomFlyingBird), "Awake", (Type[])null, (Type[])null) ?? AccessTools.DeclaredMethod(typeof(RandomFlyingBird), "Start", (Type[])null, (Type[])null); } [HarmonyPostfix] private static void Postfix(RandomFlyingBird __instance, ZNetView ___m_nview) { AddBirdCache(__instance, ___m_nview); } } [HarmonyPatch] internal static class Minimap_OnDestroy_Patch { [HarmonyPrepare] private static bool Prepare(MethodBase original) { if (!(original != null)) { return AccessTools.DeclaredMethod(typeof(Minimap), "OnDestroy", (Type[])null, (Type[])null) != null; } return true; } [HarmonyTargetMethod] private static MethodBase TargetMethod() { return AccessTools.DeclaredMethod(typeof(Minimap), "OnDestroy", (Type[])null, (Type[])null); } [HarmonyPostfix] private static void Postfix() { PinIndex.Clear(); MineRock5Cache.Clear(); } } private static readonly List ResetSharedMapDataSnapshot = new List(); [HarmonyPostfix] [HarmonyPatch(typeof(Fish), "Start")] private static void Fish_Start_Postfix(Fish __instance, ZNetView ___m_nview) { if (Object.op_Implicit((Object)(object)___m_nview) && ___m_nview.GetZDO() != null) { ((Component)__instance).gameObject.AddComponent(); } } private static void AddBirdCache(RandomFlyingBird bird, ZNetView zNetView) { if (Object.op_Implicit((Object)(object)zNetView) && zNetView.GetZDO() != null && (Object)(object)((Component)bird).GetComponent() == (Object)null) { ((Component)bird).gameObject.AddComponent(); } } [HarmonyPostfix] [HarmonyPatch(typeof(Ship), "Awake")] private static void Ship_Awake_Postfix(Ship __instance, ZNetView ___m_nview) { if (Object.op_Implicit((Object)(object)___m_nview) && ___m_nview.GetZDO() != null) { ((Component)__instance).gameObject.AddComponent(); } } [HarmonyPostfix] [HarmonyPatch(typeof(MineRock5), "Awake")] private static void MineRock5_Awake_Postfix(MineRock5 __instance) { (((Component)__instance).gameObject.GetComponent() ?? ((Component)__instance).gameObject.AddComponent()).Initialize(__instance); } [HarmonyPostfix] [HarmonyPatch(typeof(Minimap), "Start")] private static void Minimap_Start_Postfix() { IconPack.Initialize(); Map.OnMinimapStart(); } [HarmonyPostfix] [HarmonyPatch(typeof(Minimap), "UpdateMap")] private static void Minimap_UpdateMap_Postfix(Player player, float dt, bool takeInput) { AutomaticMapping.Mapping(player, dt, takeInput); } [HarmonyPrefix] [HarmonyPatch(typeof(Minimap), "OnMapLeftClick")] private static bool Minimap_OnMapLeftClick_Prefix(Minimap __instance) { return !Navigation.TryHandleMapClick(__instance); } [HarmonyTranspiler] [HarmonyPatch(typeof(Minimap), "OnMapLeftClick")] private static IEnumerable Minimap_OnMapLeftClick_Transpiler(IEnumerable instructions, ILGenerator generator) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Expected O, but got Unknown //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Expected O, but got Unknown //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Expected O, but got Unknown //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Expected O, but got Unknown //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Expected O, but got Unknown //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Expected O, but got Unknown //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Expected O, but got Unknown //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Expected O, but got Unknown //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Expected O, but got Unknown //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Expected O, but got Unknown //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Expected O, but got Unknown //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Expected O, but got Unknown Label label = default(Label); return new CodeMatcher(instructions, generator).MatchEndForward((CodeMatch[])(object)new CodeMatch[2] { new CodeMatch((OpCode?)OpCodes.Call, (object)AccessTools.Method(typeof(Minimap), "ScreenToWorldPoint", (Type[])null, (Type[])null), (string)null), new CodeMatch((OpCode?)OpCodes.Stloc_0, (object)null, (string)null) }).Advance(1).CreateLabel(ref label) .Insert((CodeInstruction[])(object)new CodeInstruction[11] { new CodeInstruction(OpCodes.Ldloc_0, (object)null), new CodeInstruction(OpCodes.Ldarg_0, (object)null), new CodeInstruction(OpCodes.Ldfld, (object)AccessTools.Field(typeof(Minimap), "m_removeRadius")), new CodeInstruction(OpCodes.Ldarg_0, (object)null), new CodeInstruction(OpCodes.Ldfld, (object)AccessTools.Field(typeof(Minimap), "m_largeZoom")), new CodeInstruction(OpCodes.Ldc_R4, (object)2f), new CodeInstruction(OpCodes.Mul, (object)null), new CodeInstruction(OpCodes.Mul, (object)null), new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(AutomaticMapping), "SetSaveFlag", (Type[])null, (Type[])null)), new CodeInstruction(OpCodes.Brfalse_S, (object)label), new CodeInstruction(OpCodes.Ret, (object)null) }) .InstructionEnumeration(); } [HarmonyTranspiler] [HarmonyPatch(typeof(Minimap), "UpdateMap")] private static IEnumerable Minimap_UpdateMap_Transpiler(IEnumerable instructions, ILGenerator generator) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Expected O, but got Unknown //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Expected O, but got Unknown //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Expected O, but got Unknown //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Expected O, but got Unknown //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Expected O, but got Unknown //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Expected O, but got Unknown //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Expected O, but got Unknown //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Expected O, but got Unknown //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Expected O, but got Unknown //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Expected O, but got Unknown //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Expected O, but got Unknown //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Expected O, but got Unknown //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Expected O, but got Unknown //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Expected O, but got Unknown Label label = default(Label); return new CodeMatcher(instructions, generator).MatchEndForward((CodeMatch[])(object)new CodeMatch[2] { new CodeMatch((OpCode?)OpCodes.Call, (object)AccessTools.Method(typeof(Minimap), "GetClosestPin", (Type[])null, (Type[])null), (string)null), new CodeMatch((OpCode?)OpCodes.Stloc_S, (object)null, (string)null) }).MatchStartForward((CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Brfalse, (object)null, (string)null) }).Advance(1) .CreateLabel(ref label) .Advance(-1) .Insert((CodeInstruction[])(object)new CodeInstruction[12] { new CodeInstruction(OpCodes.Brtrue_S, (object)label), new CodeInstruction(OpCodes.Ldloc_S, (object)8), new CodeInstruction(OpCodes.Ldarg_0, (object)null), new CodeInstruction(OpCodes.Ldfld, (object)AccessTools.Field(typeof(Minimap), "m_removeRadius")), new CodeInstruction(OpCodes.Ldarg_0, (object)null), new CodeInstruction(OpCodes.Ldfld, (object)AccessTools.Field(typeof(Minimap), "m_largeZoom")), new CodeInstruction(OpCodes.Ldc_R4, (object)2f), new CodeInstruction(OpCodes.Mul, (object)null), new CodeInstruction(OpCodes.Mul, (object)null), new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(AutomaticMapping), "SetSaveFlag", (Type[])null, (Type[])null)), new CodeInstruction(OpCodes.Pop, (object)null), new CodeInstruction(OpCodes.Ldc_I4_0, (object)null) }) .InstructionEnumeration(); } [HarmonyTranspiler] [HarmonyPatch(typeof(Minimap), "UpdatePins")] private static IEnumerable Minimap_UpdatePins_Transpiler(IEnumerable instructions, ILGenerator generator) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Expected O, but got Unknown //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Expected O, but got Unknown return new CodeMatcher(instructions, generator).MatchEndForward((CodeMatch[])(object)new CodeMatch[4] { new CodeMatch((OpCode?)OpCodes.Ldloc_1, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Ldc_R4, (object)2f, (string)null), new CodeMatch((OpCode?)OpCodes.Mul, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Stloc_S, (object)null, (string)null) }).Repeat((Action)delegate(CodeMatcher x) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Expected O, but got Unknown //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Expected O, but got Unknown object operand = x.Operand; x.Advance(1); x.InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[4] { new CodeInstruction(OpCodes.Ldloc_S, (object)4), new CodeInstruction(OpCodes.Ldloc_S, operand), new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(IconPack), "ResizeIcon", (Type[])null, (Type[])null)), new CodeInstruction(OpCodes.Stloc_S, operand) }); }, (Action)null).InstructionEnumeration(); } [HarmonyPrefix] [HarmonyPatch(typeof(Minimap), "UpdatePins")] private static void Minimap_UpdatePins_Prefix() { AutomaticMapping.AnimatePins(); } [HarmonyTranspiler] [HarmonyPatch(typeof(Minimap), "AddPin")] private static IEnumerable Minimap_AddPin_Transpiler(IEnumerable instructions, ILGenerator generator) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Expected O, but got Unknown //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Expected O, but got Unknown //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Expected O, but got Unknown //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Expected O, but got Unknown //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Expected O, but got Unknown //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Expected O, but got Unknown CodeMatcher obj = new CodeMatcher(instructions, generator).MatchEndForward((CodeMatch[])(object)new CodeMatch[4] { new CodeMatch((OpCode?)OpCodes.Ldloc_0, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Ldfld, (object)AccessTools.Field(typeof(PinData), "m_name"), (string)null), new CodeMatch((OpCode?)OpCodes.Call, (object)AccessTools.Method(typeof(string), "IsNullOrEmpty", (Type[])null, (Type[])null), (string)null), new CodeMatch((OpCode?)OpCodes.Brtrue, (object)null, (string)null) }); object operand = obj.Operand; obj.Set(OpCodes.Brtrue_S, operand); return obj.Advance(1).Insert((CodeInstruction[])(object)new CodeInstruction[3] { new CodeInstruction(OpCodes.Ldloc_0, (object)null), new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(IconPack), "IsNameTagHidden", (Type[])null, (Type[])null)), new CodeInstruction(OpCodes.Brtrue_S, operand) }).InstructionEnumeration(); } [HarmonyPostfix] [HarmonyPatch(typeof(Minimap), "AddPin")] private static void Minimap_AddPin_Postfix(PinData __result) { PinIndex.Track(__result); } [HarmonyPostfix] [HarmonyPatch(typeof(Minimap), "RemovePin", new Type[] { typeof(PinData) })] private static void Minimap_RemovePin_Postfix(PinData pin) { if (pin != null) { AutomaticMapping.OnRemovePin(pin); } } [HarmonyPostfix] [HarmonyPatch(typeof(Minimap), "ClearPins")] private static void Minimap_ClearPins_Postfix() { PinIndex.Clear(); } [HarmonyPrefix] [HarmonyPatch(typeof(Minimap), "ResetSharedMapData")] private static void Minimap_ResetSharedMapData_Prefix() { ResetSharedMapDataSnapshot.Clear(); List allPins = Map.GetAllPins(); for (int i = 0; i < allPins.Count; i++) { PinData val = allPins[i]; if (val != null && val.m_ownerID != 0L) { ResetSharedMapDataSnapshot.Add(val); } } } [HarmonyPostfix] [HarmonyPatch(typeof(Minimap), "ResetSharedMapData")] private static void Minimap_ResetSharedMapData_Postfix() { for (int i = 0; i < ResetSharedMapDataSnapshot.Count; i++) { PinIndex.Untrack(ResetSharedMapDataSnapshot[i]); } ResetSharedMapDataSnapshot.Clear(); } [HarmonyTranspiler] [HarmonyPatch(typeof(Pickable), "SetPicked")] private static IEnumerable Pickable_SetPicked_Transpiler(IEnumerable instructions) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Expected O, but got Unknown //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Expected O, but got Unknown //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Expected O, but got Unknown //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Expected O, but got Unknown //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Expected O, but got Unknown return new CodeMatcher(instructions, (ILGenerator)null).End().MatchStartBackwards((CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Callvirt, (object)AccessTools.Method(typeof(ZNetView), "Destroy", (Type[])null, (Type[])null), (string)null) }).MatchStartBackwards((CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Ldarg_0, (object)null, (string)null) }) .Insert((CodeInstruction[])(object)new CodeInstruction[4] { new CodeInstruction(OpCodes.Ldarg_0, (object)null), new CodeInstruction(OpCodes.Ldarg_0, (object)null), new CodeInstruction(OpCodes.Ldfld, (object)AccessTools.Field(typeof(Pickable), "m_nview")), new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(StaticObjectMapping), "OnObjectDestroy", (Type[])null, (Type[])null)) }) .InstructionEnumeration(); } [HarmonyTranspiler] [HarmonyPatch(typeof(MineRock5), "DamageArea")] private static IEnumerable MineRock5_DamageArea_Transpiler(IEnumerable instructions) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Expected O, but got Unknown //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected O, but got Unknown //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Expected O, but got Unknown //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Expected O, but got Unknown //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Expected O, but got Unknown //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Expected O, but got Unknown //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Expected O, but got Unknown return new CodeMatcher(instructions, (ILGenerator)null).End().MatchStartBackwards((CodeMatch[])(object)new CodeMatch[3] { new CodeMatch((OpCode?)OpCodes.Ldarg_0, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Ldfld, (object)AccessTools.Field(typeof(MineRock5), "m_nview"), (string)null), new CodeMatch((OpCode?)OpCodes.Callvirt, (object)AccessTools.Method(typeof(ZNetView), "Destroy", (Type[])null, (Type[])null), (string)null) }).Advance(1) .Insert((CodeInstruction[])(object)new CodeInstruction[4] { new CodeInstruction(OpCodes.Ldarg_0, (object)null), new CodeInstruction(OpCodes.Ldarg_0, (object)null), new CodeInstruction(OpCodes.Ldfld, (object)AccessTools.Field(typeof(MineRock5), "m_nview")), new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(StaticObjectMapping), "OnObjectDestroy", (Type[])null, (Type[])null)) }) .InstructionEnumeration(); } [HarmonyPostfix] [HarmonyPatch(typeof(Destructible), "Awake")] private static void Destructible_Awake_Postfix(Destructible __instance, ZNetView ___m_nview) { if (Object.op_Implicit((Object)(object)___m_nview) && ___m_nview.GetZDO() != null) { Destructible obj = __instance; obj.m_onDestroyed = (Action)Delegate.Combine(obj.m_onDestroyed, (Action)delegate { StaticObjectMapping.OnObjectDestroy((Component)(object)__instance, ___m_nview); }); } } [HarmonyPostfix] [HarmonyPatch(typeof(TeleportWorld), "Awake")] private static void TeleportWorld_Awake_Postfix(TeleportWorld __instance, ZNetView ___m_nview) { if ((Object)(object)___m_nview == (Object)null || ___m_nview.GetZDO() == null) { return; } WearNTear component = ((Component)__instance).GetComponent(); if (!Object.op_Implicit((Object)(object)component)) { return; } component.m_onDestroyed = (Action)Delegate.Combine(component.m_onDestroyed, (Action)delegate { //IL_001b: Unknown result type (might be due to invalid IL or missing references) if (Config.EnableAutomaticMapping && Config.AllowPinningPortal) { Map.RemovePin(((Component)__instance).transform.position); } }); } [HarmonyPostfix] [HarmonyPatch(typeof(Vagon), "Awake")] private static void Vagon_Awake_Postfix(Vagon __instance, ZNetView ___m_nview) { if ((Object)(object)___m_nview == (Object)null || ___m_nview.GetZDO() == null) { return; } WearNTear component = ((Component)__instance).GetComponent(); if (Object.op_Implicit((Object)(object)component)) { component.m_onDestroyed = (Action)Delegate.Combine(component.m_onDestroyed, (Action)delegate { DynamicObjectMapping.OnObjectDestroy((Component)(object)__instance); }); } } } internal readonly struct CellKey : IEquatable { public readonly int Cx; public readonly int Cz; public CellKey(int cx, int cz) { Cx = cx; Cz = cz; } public bool Equals(CellKey other) { if (Cx == other.Cx) { return Cz == other.Cz; } return false; } public override bool Equals(object obj) { if (obj is CellKey other) { return Equals(other); } return false; } public override int GetHashCode() { return (Cx * 397) ^ Cz; } } internal static class PinIndex { public const float CellSize = 32f; private static readonly Dictionary> Cells = new Dictionary>(); private static readonly Dictionary PinCell = new Dictionary(); private static readonly List Transients = new List(); public static IReadOnlyList TransientPins => Transients; public static bool IsTransientType(PinType type) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected I4, but got Unknown switch (type - 5) { case 0: case 2: case 5: case 6: case 7: case 8: return true; default: return false; } } public static CellKey CellOf(Vector3 pos) { //IL_0000: 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) return new CellKey(Mathf.FloorToInt(pos.x / 32f), Mathf.FloorToInt(pos.z / 32f)); } public static void Track(PinData pin) { //IL_0005: 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) if (pin == null) { return; } if (IsTransientType(pin.m_type)) { if (!Transients.Contains(pin)) { Transients.Add(pin); } } else if (!PinCell.ContainsKey(pin)) { CellKey cellKey = CellOf(pin.m_pos); if (!Cells.TryGetValue(cellKey, out var value)) { value = new List(); Cells[cellKey] = value; } value.Add(pin); PinCell[pin] = cellKey; } } public static void Untrack(PinData pin) { if (pin == null) { return; } if (PinCell.TryGetValue(pin, out var value)) { PinCell.Remove(pin); if (Cells.TryGetValue(value, out var value2)) { value2.Remove(pin); if (value2.Count == 0) { Cells.Remove(value); } } } Transients.Remove(pin); } public static bool Contains(PinData pin) { if (pin == null) { return false; } if (!PinCell.ContainsKey(pin)) { return Transients.Contains(pin); } return true; } public static void Move(PinData pin, Vector3 newPos) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) if (pin == null || !PinCell.TryGetValue(pin, out var value)) { return; } CellKey cellKey = CellOf(newPos); if (value.Equals(cellKey)) { return; } if (Cells.TryGetValue(value, out var value2)) { value2.Remove(pin); if (value2.Count == 0) { Cells.Remove(value); } } if (!Cells.TryGetValue(cellKey, out var value3)) { value3 = new List(); Cells[cellKey] = value3; } value3.Add(pin); PinCell[pin] = cellKey; } public static void Clear() { Cells.Clear(); PinCell.Clear(); Transients.Clear(); } public static bool TryGetCell(CellKey key, out List pins) { return Cells.TryGetValue(key, out pins); } } internal enum PinKind { Flora, Mineral, Spawner, Other, Portal, Dungeon, Spot } internal enum PinSourceDomain { Component, Location } internal struct ClassifiedStaticObject { public Component Component; public PinKind Kind; public string Identifier; public Vector3 Position; public string SourceToken; } internal sealed class PinCacheEntry { public PinData PinData; public PinKind Kind; public string Identifier; public string SourceToken; public PinSourceDomain Domain; public int LastSeenSweep; } internal struct PendingScanSnapshot { public Vector3 Origin; public float Range; public int Mask; public int StaticClassifierVersion; } internal struct PendingTile { public Vector3 Center; public float HalfXZ; public int Depth; } } namespace Automatics.AutomaticFeeding { [Flags] internal enum AnimalType : long { [UsedImplicitly] None = 0L, [LocalizedDescription("automatics", "@config_automatic_feeding_animal_type_wild")] Wild = 1L, [LocalizedDescription("automatics", "@config_automatic_feeding_animal_type_tamed")] Tamed = 2L, [UsedImplicitly] [LocalizedDescription("automatics", "@select_all")] All = 3L } [DisallowMultipleComponent] internal class AutomaticFeeding : MonoBehaviour { private static readonly IList AllInstance; private Tameable _tamable; private Character _character; private MonsterAI _monsterAI; private BaseAI _baseAI; private float _consumeSearchTimer; private Container _closestFeedBox; private Humanoid _closestFeeder; private ItemData _consumeTargetItem; static AutomaticFeeding() { AllInstance = new List(); } private void Awake() { _tamable = ((Component)this).GetComponent(); _character = ((Component)this).GetComponent(); _monsterAI = ((Component)this).GetComponent(); _baseAI = ((Component)this).GetComponent(); AllInstance.Add(this); } private void OnDestroy() { AllInstance.Remove(this); _baseAI = null; _monsterAI = null; _tamable = null; _character = null; _closestFeeder = null; _closestFeedBox = null; _consumeTargetItem = null; } public static bool CancelAttackOnFeedBox(BaseAI baseAI, StaticTarget target) { return AllInstance.Any((AutomaticFeeding x) => (Object)(object)x._baseAI == (Object)(object)baseAI && x.CancelAttackOnFeedBox(target)); } public static bool Feeding(MonsterAI monsterAI, Humanoid humanoid, float delta) { return AllInstance.Any((AutomaticFeeding x) => (Object)(object)x._monsterAI == (Object)(object)monsterAI && x.Feeding(humanoid, delta)); } private bool HasNetworkOwnership() { return Objects.HasValidOwnership((Component)(object)_character); } private bool CancelAttackOnFeedBox(StaticTarget target) { if (!HasNetworkOwnership()) { return false; } if (!_character.IsTamed() && !Logics.IsAllowToFeedFromContainer(AnimalType.Wild)) { return false; } Container componentInChildren = ((Component)target).GetComponentInChildren(); if ((Object)(object)componentInChildren == (Object)null) { return false; } if (componentInChildren != _closestFeedBox) { return componentInChildren.GetInventory().GetAllItems().Any(CanConsume); } return true; } private bool Feeding(Humanoid humanoid, float delta) { //IL_0100: 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_0105: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Unknown result type (might be due to invalid IL or missing references) if (!HasNetworkOwnership()) { return false; } if (_monsterAI.m_consumeItems == null || !_monsterAI.m_consumeItems.Any()) { return false; } _consumeSearchTimer += delta; if (_consumeSearchTimer >= _monsterAI.m_consumeSearchInterval) { _consumeSearchTimer = 0f; if (!_tamable.IsHungry()) { return false; } UpdateFeedInfo(); } if (!Object.op_Implicit((Object)(object)_closestFeedBox) && !Object.op_Implicit((Object)(object)_closestFeeder)) { return false; } if (_consumeTargetItem == null) { return false; } bool flag = Object.op_Implicit((Object)(object)_closestFeedBox); Inventory val = (flag ? _closestFeedBox.GetInventory() : _closestFeeder.GetInventory()); if (!val.HaveItem(_consumeTargetItem.m_shared.m_name, true)) { return false; } bool flag2 = true; if (Config.NeedGetCloseToEatTheFeed) { flag2 = false; Vector3 point = (flag ? ((Component)_closestFeedBox).transform.position : ((Component)_closestFeeder).transform.position); float dist = _monsterAI.m_consumeRange + 1f; if (MoveTo(delta, point, dist, run: false)) { LookAt(point); flag2 = IsLookingAt(point, 20f); } } if (flag2) { if (flag && Objects.GetZNetView((Component)(object)_closestFeedBox, out var zNetView) && zNetView.IsValid()) { zNetView.ClaimOwnership(); } if (val.RemoveOneItem(_consumeTargetItem)) { _monsterAI.m_onConsumedItem?.Invoke(_consumeTargetItem.m_dropPrefab.GetComponent()); humanoid.m_consumeItemEffects.Create(((Component)_baseAI).transform.position, Quaternion.identity, (Transform)null, 1f, -1); Reflections.GetField(_baseAI, "m_animator").SetTrigger("consume"); _closestFeeder = null; _closestFeedBox = null; _consumeTargetItem = null; } } return true; } private void UpdateFeedInfo() { float num = Config.FeedSearchRange; if (num <= 0f) { num = _monsterAI.m_consumeSearchRange; } _closestFeeder = null; _closestFeedBox = null; _consumeTargetItem = null; AnimalType type = (AnimalType)(_character.IsTamed() ? 2 : 1); if (Logics.IsAllowToFeedFromContainer(type)) { FindFeedBox(num); } if ((Object)(object)_closestFeedBox == (Object)null && Logics.IsAllowToFeedFromPlayer(type)) { FindFeeder(num); } } private void FindFeedBox(float range) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0042: 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) bool needGetCloseToEatTheFeed = Config.NeedGetCloseToEatTheFeed; Vector3 position = ((Component)_baseAI).transform.position; float num = float.MaxValue; foreach (Container item in InstanceCache.GetAllInstance()) { Vector3 position2 = ((Component)item).transform.position; float num2 = Vector3.Distance(position2, position); if (!(num2 > range) && !(num2 >= num) && (!needGetCloseToEatTheFeed || HavePath(position2))) { ItemData val = ((IEnumerable)item.GetInventory().GetAllItems()).FirstOrDefault((Func)CanConsume); if (val != null) { num = num2; _closestFeedBox = item; _consumeTargetItem = val; } } } } private void FindFeeder(float searchRange) { //IL_0021: 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_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: 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_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return; } bool needGetCloseToEatTheFeed = Config.NeedGetCloseToEatTheFeed; Vector3 position = ((Component)_baseAI).transform.position; Vector3 position2 = ((Component)localPlayer).transform.position; if (!(Vector3.Distance(position2, position) > searchRange) && (!needGetCloseToEatTheFeed || HavePath(position2))) { ItemData val = ((IEnumerable)((Humanoid)localPlayer).GetInventory().GetAllItems()).FirstOrDefault((Func)CanConsume); if (val != null) { _closestFeeder = (Humanoid)(object)localPlayer; _consumeTargetItem = val; } } } private bool CanConsume(ItemData item) { return Reflections.InvokeMethod(_monsterAI, "CanConsume", new object[1] { item }); } private bool HavePath(Vector3 target) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) return Reflections.InvokeMethod(_baseAI, "HavePath", new object[1] { target }); } private bool MoveTo(float dt, Vector3 point, float dist, bool run) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) return Reflections.InvokeMethod(_baseAI, "MoveTo", new object[4] { dt, point, dist, run }); } private void LookAt(Vector3 point) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) Reflections.InvokeMethod(_baseAI, "LookAt", point); } private bool IsLookingAt(Vector3 point, float minAngle) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) return Reflections.InvokeMethod(_baseAI, "IsLookingAt", new object[2] { point, minAngle }); } } internal static class Config { private const string Section = "automatic_feeding"; private static ConfigEntry _module; private static ConfigEntry _enableAutomaticFeeding; private static ConfigEntry _feedSearchRange; private static ConfigEntry _needGetCloseToEatTheFeed; private static ConfigEntry _allowToFeedFromContainer; private static ConfigEntry _allowToFeedFromPlayer; public static bool ModuleDisabled => _module.Value == AutomaticsModule.Disabled; public static bool EnableAutomaticFeeding => _enableAutomaticFeeding.Value; public static float FeedSearchRange => _feedSearchRange.Value; public static bool NeedGetCloseToEatTheFeed => _needGetCloseToEatTheFeed.Value; public static AnimalType AllowToFeedFromContainer => _allowToFeedFromContainer.Value; public static AnimalType AllowToFeedFromPlayer => _allowToFeedFromPlayer.Value; public static void Initialize() { Configuration instance = global::Automatics.Config.Instance; instance.ChangeSection("automatic_feeding"); _module = instance.Bind("module", AutomaticsModule.Enabled, null, delegate(ConfigurationManagerAttributes x) { x.DispName = Automatics.L10N.Translate("@config_common_disable_module_name"); x.Description = Automatics.L10N.Translate("@config_common_disable_module_description"); }); if (_module.Value != AutomaticsModule.Disabled) { _enableAutomaticFeeding = instance.Bind("enable_automatic_feeding", defaultValue: true); _feedSearchRange = instance.Bind("feed_search_range", 0, (0, 64)); _needGetCloseToEatTheFeed = instance.Bind("need_get_close_to_eat_the_feed", defaultValue: false); _allowToFeedFromContainer = instance.Bind("allow_to_feed_from_container", AnimalType.Tamed); _allowToFeedFromPlayer = instance.Bind("allow_to_feed_from_player", AnimalType.None); } } } internal static class Logics { public static bool IsAllowToFeedFromContainer(AnimalType type) { return (Config.AllowToFeedFromContainer & type) != 0; } public static bool IsAllowToFeedFromPlayer(AnimalType type) { return (Config.AllowToFeedFromPlayer & type) != 0; } } internal static class Module { [AutomaticsInitializer(4)] private static void Initialize() { Config.Initialize(); if (!Config.ModuleDisabled) { Harmony.CreateAndPatchAll(typeof(Patches), Automatics.GetHarmonyId("automatic-feeding")); } } } [HarmonyPatch] internal static class Patches { [HarmonyPostfix] [HarmonyPatch(typeof(Tameable), "Awake")] private static void Tameable_Awake_Postfix(Tameable __instance, ZNetView ___m_nview) { if (Object.op_Implicit((Object)(object)___m_nview) && ___m_nview.GetZDO() != null) { ((Component)__instance).gameObject.AddComponent(); } } [HarmonyPostfix] [HarmonyPatch(typeof(MonsterAI), "UpdateConsumeItem")] private static void MonsterAI_UpdateConsumeItem_Postfix(MonsterAI __instance, ref bool __result, Humanoid humanoid, float dt) { if (Config.EnableAutomaticFeeding && !__result && AutomaticFeeding.Feeding(__instance, humanoid, dt)) { __result = true; } } [HarmonyPostfix] [HarmonyPatch(typeof(BaseAI), "CanSeeTarget", new Type[] { typeof(StaticTarget) })] private static void BaseAI_CanSeeTarget_Postfix(BaseAI __instance, ref bool __result, StaticTarget target) { if (__result && Config.EnableAutomaticFeeding && AutomaticFeeding.CancelAttackOnFeedBox(__instance, target)) { __result = false; } } } } namespace Automatics.AutomaticDoor { [DisallowMultipleComponent] internal sealed class AutomaticDoor : MonoBehaviour { private const float PredictionLookAheadSeconds = 0.35f; private const float MaxPredictionDistance = 1.5f; private const float MinPredictionSpeed = 1f; private const float MinApproachDot = 0.35f; private const float CloseGracePeriod = 0.35f; private static readonly Lazy LazyPieceMask; private static readonly IList AllInstance; private Door _door; private Transform _transform; private ZNetView _zNetView; private bool _allowAutomaticDoor; private bool _allowAutomaticDoorDirty; private float _lastAutomaticOpenTime; private static int PieceMask => LazyPieceMask.Value; public static bool HasRegisteredDoor => AllInstance.Count > 0; static AutomaticDoor() { LazyPieceMask = new Lazy(() => LayerMask.GetMask(new string[7] { "Default", "static_solid", "Default_small", "piece", "piece_nonsolid", "terrain", "vehicle" })); AllInstance = new List(); } private void Awake() { _door = ((Component)this).GetComponent(); _transform = ((Component)this).transform; Objects.GetZNetView((Component)(object)_door, out _zNetView); _allowAutomaticDoorDirty = true; AllInstance.Add(this); } private void OnDestroy() { AllInstance.Remove(this); _zNetView = null; _transform = null; _door = null; } public static void MarkAllowAutomaticDoorDirty() { foreach (AutomaticDoor item in AllInstance) { if (Object.op_Implicit((Object)(object)item)) { item._allowAutomaticDoorDirty = true; } } } public static void TryOpenNearby(Player player, Vector3 velocity) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)player)) { return; } float distanceForAutomaticOpening = Config.DistanceForAutomaticOpening; if (distanceForAutomaticOpening <= 0f) { return; } float num = distanceForAutomaticOpening + GetPredictionDistance(velocity); float searchRangeSquared = num * num; for (int num2 = AllInstance.Count - 1; num2 >= 0; num2--) { AutomaticDoor automaticDoor = AllInstance[num2]; if (!IsRegistered(automaticDoor)) { AllInstance.RemoveAt(num2); } else { automaticDoor.TryOpen(player, velocity, searchRangeSquared, distanceForAutomaticOpening); } } } public static void TryCloseDoors() { float distanceForAutomaticClosing = Config.DistanceForAutomaticClosing; if (distanceForAutomaticClosing <= 0f) { return; } List allPlayers = Player.GetAllPlayers(); for (int num = AllInstance.Count - 1; num >= 0; num--) { AutomaticDoor automaticDoor = AllInstance[num]; if (!IsRegistered(automaticDoor)) { AllInstance.RemoveAt(num); } else { automaticDoor.TryClose(allPlayers, distanceForAutomaticClosing); } } } private static bool IsRegistered(AutomaticDoor automaticDoor) { if (Object.op_Implicit((Object)(object)automaticDoor) && Object.op_Implicit((Object)(object)automaticDoor._door) && Object.op_Implicit((Object)(object)automaticDoor._transform)) { return (Object)(object)automaticDoor._zNetView != (Object)null; } return false; } private static float GetPredictionDistance(Vector3 velocity) { float magnitude = ((Vector3)(ref velocity)).magnitude; if (magnitude < 1f) { return 0f; } return Mathf.Min(magnitude * 0.35f, 1.5f); } private void TryOpen(Player player, Vector3 velocity, float searchRangeSquared, float openRange) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) if (!IsValid() || !IsAllowAutomaticDoor() || IsDoorOpen() || !CanInteract() || !CanOpen(player)) { return; } Vector3 position = ((Component)player).transform.position; Vector3 position2 = _transform.position; Vector3 val = position2 - position; if (!(((Vector3)(ref val)).sqrMagnitude > searchRangeSquared) && ShouldOpen(position, velocity, openRange) && !IsExistsObstaclesBetweenTo(player)) { if (Object.op_Implicit((Object)(object)_door.m_keyItem) && (Object)(object)Player.m_localPlayer == (Object)(object)player) { ((Character)player).Message((MessageType)2, Localization.instance.Localize("$msg_door_usingkey", new string[1] { _door.m_keyItem.m_itemData.m_shared.m_name }), 0, (Sprite)null); } Door door = _door; object[] array = new object[1]; val = position - position2; array[0] = ((Vector3)(ref val)).normalized; Reflections.InvokeMethod(door, "Open", array); _lastAutomaticOpenTime = Time.time; } } private void TryClose(IEnumerable players, float closeRange) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) if (!IsValid() || !IsAllowAutomaticDoor() || !IsDoorOpen() || !CanInteract() || Time.time - _lastAutomaticOpenTime < 0.35f) { return; } Player val = null; float num = float.MaxValue; float num2 = closeRange * closeRange; Vector3 position = _transform.position; Vector3 val2; foreach (Player player in players) { if (Object.op_Implicit((Object)(object)player)) { val2 = ((Component)player).transform.position - position; float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude; if (sqrMagnitude <= num2) { return; } if (!(sqrMagnitude >= num)) { num = sqrMagnitude; val = player; } } } if (Object.op_Implicit((Object)(object)val)) { Door door = _door; object[] array = new object[1]; val2 = ((Component)val).transform.position - position; array[0] = ((Vector3)(ref val2)).normalized; Reflections.InvokeMethod(door, "Open", array); } } private bool IsAllowAutomaticDoor() { if (!_allowAutomaticDoorDirty) { return _allowAutomaticDoor; } _allowAutomaticDoor = Logics.IsAllowAutomaticDoor(_door); _allowAutomaticDoorDirty = false; return _allowAutomaticDoor; } private bool IsValid() { return Objects.HasValidOwnership(_zNetView); } private bool IsDoorOpen() { return _zNetView.GetZDO().GetInt("state", 0) != 0; } private bool CanInteract() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) if (_door.m_checkGuardStone && !PrivateArea.CheckAccess(_transform.position, 0f, true, false)) { return false; } return Reflections.InvokeMethod(_door, "CanInteract"); } private bool CanOpen(Player player) { if (Object.op_Implicit((Object)(object)_door.m_keyItem)) { return Reflections.InvokeMethod(_door, "HaveKey", new object[1] { player }); } return true; } private bool ShouldOpen(Vector3 playerPosition, Vector3 velocity, float openRange) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000c: 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) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0048: 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_005c: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) Vector3 val = _transform.position - playerPosition; float num = openRange * openRange; if (((Vector3)(ref val)).sqrMagnitude <= num) { return true; } float predictionDistance = GetPredictionDistance(velocity); if (predictionDistance <= 0f) { return false; } float magnitude = ((Vector3)(ref velocity)).magnitude; Vector3 val2 = velocity / magnitude; if (Vector3.Dot(val2, ((Vector3)(ref val)).normalized) < 0.35f) { return false; } Vector3 val3 = playerPosition + val2 * predictionDistance; Vector3 val4 = _transform.position - val3; return ((Vector3)(ref val4)).sqrMagnitude <= num; } private bool IsExistsObstaclesBetweenTo(Player player) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) Collider field = Reflections.GetField(player, "m_collider"); Vector3 val; if (field == null) { val = ((Character)player).m_eye.position; } else { Bounds bounds = field.bounds; val = ((Bounds)(ref bounds)).center; } Vector3 position = _transform.position; RaycastHit val2 = default(RaycastHit); if (!Physics.Linecast(val, position, ref val2, PieceMask)) { return false; } Door componentInParent = ((Component)((RaycastHit)(ref val2)).collider).GetComponentInParent(); if (Object.op_Implicit((Object)(object)componentInParent)) { return (Object)(object)componentInParent != (Object)(object)_door; } return Object.op_Implicit((Object)(object)((Component)((RaycastHit)(ref val2)).collider).GetComponentInParent()); } } internal static class Config { private const string Section = "automatic_door"; private static ConfigEntry _module; private static ConfigEntry _enableAutomaticDoor; private static ConfigEntry _allowAutomaticDoor; private static ConfigEntry _intervalToOpen; private static ConfigEntry _intervalToClose; private static ConfigEntry _distanceForAutomaticOpening; private static ConfigEntry _distanceForAutomaticClosing; private static ConfigEntry _automaticDoorEnableDisableToggleMessage; private static ConfigEntry _automaticDoorEnableDisableToggle; public static bool ModuleDisabled => _module.Value == AutomaticsModule.Disabled; public static bool EnableAutomaticDoor { get { return _enableAutomaticDoor.Value; } set { _enableAutomaticDoor.Value = value; } } public static StringList AllowAutomaticDoor => _allowAutomaticDoor.Value; public static float IntervalToOpen => _intervalToOpen.Value; public static float IntervalToClose => _intervalToClose.Value; public static float DistanceForAutomaticOpening => _distanceForAutomaticOpening.Value; public static float DistanceForAutomaticClosing => _distanceForAutomaticClosing.Value; public static Message AutomaticDoorEnableDisableToggleMessage => _automaticDoorEnableDisableToggleMessage.Value; public static KeyboardShortcut AutomaticDoorEnableDisableToggle => _automaticDoorEnableDisableToggle.Value; public static void Initialize() { //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) Configuration instance = global::Automatics.Config.Instance; instance.ChangeSection("automatic_door"); _module = instance.Bind("module", AutomaticsModule.Enabled, null, delegate(ConfigurationManagerAttributes x) { x.DispName = Automatics.L10N.Translate("@config_common_disable_module_name"); x.Description = Automatics.L10N.Translate("@config_common_disable_module_description"); }); if (_module.Value != AutomaticsModule.Disabled) { _enableAutomaticDoor = instance.Bind("enable_automatic_door", defaultValue: true); _allowAutomaticDoor = instance.BindValheimObjectList("allow_automatic_door", Globals.Door, null, null, new string[1] { "WoodShutter" }); _allowAutomaticDoor.SettingChanged += delegate { AutomaticDoor.MarkAllowAutomaticDoorDirty(); }; _intervalToOpen = instance.Bind("interval_to_open", 0.1f, (0f, 8f)); _intervalToClose = instance.Bind("interval_to_close", 0.1f, (0f, 8f)); _distanceForAutomaticOpening = instance.Bind("distance_for_automatic_opening", 2.5f, (1f, 8f)); _distanceForAutomaticClosing = instance.Bind("distance_for_automatic_closing", 2.5f, (1f, 8f)); _automaticDoorEnableDisableToggleMessage = instance.Bind("automatic_door_enable_disable_toggle_message", Message.Center); _automaticDoorEnableDisableToggle = instance.Bind("automatic_door_enable_disable_toggle", default(KeyboardShortcut)); instance.ChangeSection("general", 64); instance.BindCustomValheimObject("custom_door", Globals.Door).SettingChanged += delegate { AutomaticDoor.MarkAllowAutomaticDoorDirty(); }; } } } internal static class Globals { public static ValheimObject Door { get; } = new ValheimObject("door"); } internal static class Logics { public static bool IsAllowAutomaticDoor(Door door) { if (Globals.Door.GetIdentify(Objects.GetName((Component)(object)door), out var identifier)) { return Config.AllowAutomaticDoor.Contains(identifier); } return false; } } internal static class Module { private struct PlayerMotionState { public Vector3 LastPosition; public float LastTime; public bool HasLastPosition; } private static readonly Dictionary PlayerMotionStates; private static readonly HashSet ActivePlayerStateKeys; private static readonly List PlayerStateKeysBuffer; private static float _openTimer; private static float _closeTimer; static Module() { PlayerMotionStates = new Dictionary(); ActivePlayerStateKeys = new HashSet(); PlayerStateKeysBuffer = new List(); } [AutomaticsInitializer(1)] private static void Initialize() { Config.Initialize(); if (!Config.ModuleDisabled) { Hooks.OnPlayerAwake = (Action)Delegate.Combine(Hooks.OnPlayerAwake, (Action)delegate { ResetState(); }); Hooks.OnPlayerUpdate = (Action)Delegate.Combine(Hooks.OnPlayerUpdate, new Action(OnPlayerUpdate)); Hooks.OnPlayerFixedUpdate = (Action)Delegate.Combine(Hooks.OnPlayerFixedUpdate, new Action(OnPlayerFixedUpdate)); Hooks.OnDedicatedServerFixedUpdate = (Action)Delegate.Combine(Hooks.OnDedicatedServerFixedUpdate, new Action(OnDedicatedServerFixedUpdate)); Harmony.CreateAndPatchAll(typeof(Patches), Automatics.GetHarmonyId("automatic-door")); } } private static void ResetState() { _openTimer = 0f; _closeTimer = 0f; PlayerMotionStates.Clear(); ActivePlayerStateKeys.Clear(); PlayerStateKeysBuffer.Clear(); } private static void ResetTimers() { _openTimer = 0f; _closeTimer = 0f; } private static void OnPlayerUpdate(Player player, bool takeInput) { //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_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Player.m_localPlayer != (Object)(object)player || !((Character)player).IsOwner() || !takeInput) { return; } KeyboardShortcut automaticDoorEnableDisableToggle = Config.AutomaticDoorEnableDisableToggle; if (((KeyboardShortcut)(ref automaticDoorEnableDisableToggle)).IsDown()) { Config.EnableAutomaticDoor = !Config.EnableAutomaticDoor; Message automaticDoorEnableDisableToggleMessage = Config.AutomaticDoorEnableDisableToggleMessage; if (automaticDoorEnableDisableToggleMessage != 0) { string text = Automatics.L10N.Localize("@message_automatic_door_enable_disable_toggle", Config.EnableAutomaticDoor ? "@enabled" : "@disabled"); MessageType val = (MessageType)((automaticDoorEnableDisableToggleMessage != Message.Center) ? 1 : 2); ((Character)player).Message(val, text, 0, (Sprite)null); } } } private static void OnDedicatedServerFixedUpdate(float delta) { UpdateAutomaticDoor(Player.GetAllPlayers(), delta); } private static void OnPlayerFixedUpdate(Player player, float delta) { if (!((Object)(object)Player.m_localPlayer != (Object)(object)player) && ((Character)player).IsOwner()) { UpdateAutomaticDoor(Player.GetAllPlayers(), delta); } } private static void UpdateAutomaticDoor(IList players, float delta) { //IL_0070: Unknown result type (might be due to invalid IL or missing references) CleanupPlayerStates(players); if (IsGamePaused()) { InvalidatePlayerMotion(); return; } if (!Config.EnableAutomaticDoor || !AutomaticDoor.HasRegisteredDoor) { ResetTimers(); return; } if (Config.IntervalToOpen >= 0.1f) { _openTimer += delta; if (_openTimer >= Config.IntervalToOpen) { _openTimer = 0f; foreach (Player player in players) { if (Object.op_Implicit((Object)(object)player)) { AutomaticDoor.TryOpenNearby(player, GetVelocity(player, delta)); } } } } else { _openTimer = 0f; } if (Config.IntervalToClose >= 0.1f) { _closeTimer += delta; if (_closeTimer >= Config.IntervalToClose) { _closeTimer = 0f; AutomaticDoor.TryCloseDoors(); } } else { _closeTimer = 0f; } } private static bool IsGamePaused() { if ((Object)(object)Game.instance != (Object)null) { return Game.IsPaused(); } return false; } private static int GetPlayerStateKey(Player player) { return ((Object)player).GetInstanceID(); } private static void CleanupPlayerStates(IList players) { if (PlayerMotionStates.Count == 0) { return; } ActivePlayerStateKeys.Clear(); foreach (Player player in players) { if (Object.op_Implicit((Object)(object)player)) { ActivePlayerStateKeys.Add(GetPlayerStateKey(player)); } } PlayerStateKeysBuffer.Clear(); foreach (int key in PlayerMotionStates.Keys) { if (!ActivePlayerStateKeys.Contains(key)) { PlayerStateKeysBuffer.Add(key); } } foreach (int item in PlayerStateKeysBuffer) { PlayerMotionStates.Remove(item); } } private static void InvalidatePlayerMotion() { if (PlayerMotionStates.Count == 0) { return; } PlayerStateKeysBuffer.Clear(); foreach (int key in PlayerMotionStates.Keys) { PlayerStateKeysBuffer.Add(key); } foreach (int item in PlayerStateKeysBuffer) { PlayerMotionState value = PlayerMotionStates[item]; value.HasLastPosition = false; PlayerMotionStates[item] = value; } } private static Vector3 GetVelocity(Player player, float delta) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0073: 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_005b: 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_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) int playerStateKey = GetPlayerStateKey(player); if (!PlayerMotionStates.TryGetValue(playerStateKey, out var value)) { value = default(PlayerMotionState); } Vector3 position = ((Component)player).transform.position; float time = Time.time; Vector3 result = Vector3.zero; if (value.HasLastPosition) { float num = time - value.LastTime; if (num > Mathf.Epsilon && num < 1f) { result = (position - value.LastPosition) / num; } } value.LastPosition = position; value.LastTime = time; value.HasLastPosition = true; PlayerMotionStates[playerStateKey] = value; return result; } } [HarmonyPatch] internal static class Patches { [HarmonyPostfix] [HarmonyPatch(typeof(Door), "Awake")] private static void Door_Awake_Postfix(Door __instance, ZNetView ___m_nview) { if (Object.op_Implicit((Object)(object)___m_nview) && ___m_nview.GetZDO() != null && !Object.op_Implicit((Object)(object)((Component)__instance).GetComponent())) { ((Component)__instance).gameObject.AddComponent(); } } } } [CompilerGenerated] internal sealed class <44721b2b-cf52-4a4a-89f2-de845b24cc0d> { [StructLayout(LayoutKind.Explicit, Pack = 1, Size = 32)] private struct __StaticArrayInitTypeSize=32 { } internal static readonly __StaticArrayInitTypeSize=32 045487DC21A65255AB8C67A2F4DE70EAFD7562D32E5E856A58DB4E85A4EC8927/* Not supported: data(00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00) */; internal static readonly long 52E5A2D9F0BC9DF8C1DC20A1983BE35AD3490120BF21F6328E54E10A37E9FE4C/* Not supported: data(22 00 2C 00 0D 00 0A 00) */; } namespace LitJson { internal enum JsonType { None, Object, Array, String, Int, Long, Double, Boolean } internal interface IJsonWrapper : IList, ICollection, IEnumerable, IOrderedDictionary, IDictionary { bool IsArray { get; } bool IsBoolean { get; } bool IsDouble { get; } bool IsInt { get; } bool IsLong { get; } bool IsObject { get; } bool IsString { get; } bool GetBoolean(); double GetDouble(); int GetInt(); JsonType GetJsonType(); long GetLong(); string GetString(); void SetBoolean(bool val); void SetDouble(double val); void SetInt(int val); void SetJsonType(JsonType type); void SetLong(long val); void SetString(string val); string ToJson(); void ToJson(JsonWriter writer); } internal class JsonData : IJsonWrapper, IList, ICollection, IEnumerable, IOrderedDictionary, IDictionary, IEquatable { private IList inst_array; private bool inst_boolean; private double inst_double; private int inst_int; private long inst_long; private IDictionary inst_object; private string inst_string; private string json; private JsonType type; private IList> object_list; public int Count => EnsureCollection().Count; public bool IsArray => type == JsonType.Array; public bool IsBoolean => type == JsonType.Boolean; public bool IsDouble => type == JsonType.Double; public bool IsInt => type == JsonType.Int; public bool IsLong => type == JsonType.Long; public bool IsObject => type == JsonType.Object; public bool IsString => type == JsonType.String; public ICollection Keys { get { EnsureDictionary(); return inst_object.Keys; } } int ICollection.Count => Count; bool ICollection.IsSynchronized => EnsureCollection().IsSynchronized; object ICollection.SyncRoot => EnsureCollection().SyncRoot; bool IDictionary.IsFixedSize => EnsureDictionary().IsFixedSize; bool IDictionary.IsReadOnly => EnsureDictionary().IsReadOnly; ICollection IDictionary.Keys { get { EnsureDictionary(); IList list = new List(); foreach (KeyValuePair item in object_list) { list.Add(item.Key); } return (ICollection)list; } } ICollection IDictionary.Values { get { EnsureDictionary(); IList list = new List(); foreach (KeyValuePair item in object_list) { list.Add(item.Value); } return (ICollection)list; } } bool IJsonWrapper.IsArray => IsArray; bool IJsonWrapper.IsBoolean => IsBoolean; bool IJsonWrapper.IsDouble => IsDouble; bool IJsonWrapper.IsInt => IsInt; bool IJsonWrapper.IsLong => IsLong; bool IJsonWrapper.IsObject => IsObject; bool IJsonWrapper.IsString => IsString; bool IList.IsFixedSize => EnsureList().IsFixedSize; bool IList.IsReadOnly => EnsureList().IsReadOnly; object IDictionary.this[object key] { get { return EnsureDictionary()[key]; } set { if (!(key is string)) { throw new ArgumentException("The key has to be a string"); } JsonData value2 = ToJsonData(value); this[(string)key] = value2; } } object IOrderedDictionary.this[int idx] { get { EnsureDictionary(); return object_list[idx].Value; } set { EnsureDictionary(); JsonData value2 = ToJsonData(value); KeyValuePair keyValuePair = object_list[idx]; inst_object[keyValuePair.Key] = value2; KeyValuePair value3 = new KeyValuePair(keyValuePair.Key, value2); object_list[idx] = value3; } } object IList.this[int index] { get { return EnsureList()[index]; } set { EnsureList(); JsonData value2 = ToJsonData(value); this[index] = value2; } } public JsonData this[string prop_name] { get { EnsureDictionary(); return inst_object[prop_name]; } set { EnsureDictionary(); KeyValuePair keyValuePair = new KeyValuePair(prop_name, value); if (inst_object.ContainsKey(prop_name)) { for (int i = 0; i < object_list.Count; i++) { if (object_list[i].Key == prop_name) { object_list[i] = keyValuePair; break; } } } else { object_list.Add(keyValuePair); } inst_object[prop_name] = value; json = null; } } public JsonData this[int index] { get { EnsureCollection(); if (type == JsonType.Array) { return inst_array[index]; } return object_list[index].Value; } set { EnsureCollection(); if (type == JsonType.Array) { inst_array[index] = value; } else { KeyValuePair keyValuePair = object_list[index]; KeyValuePair value2 = new KeyValuePair(keyValuePair.Key, value); object_list[index] = value2; inst_object[keyValuePair.Key] = value; } json = null; } } public bool ContainsKey(string key) { EnsureDictionary(); return inst_object.Keys.Contains(key); } public JsonData() { } public JsonData(bool boolean) { type = JsonType.Boolean; inst_boolean = boolean; } public JsonData(double number) { type = JsonType.Double; inst_double = number; } public JsonData(int number) { type = JsonType.Int; inst_int = number; } public JsonData(long number) { type = JsonType.Long; inst_long = number; } public JsonData(object obj) { if (obj is bool) { type = JsonType.Boolean; inst_boolean = (bool)obj; return; } if (obj is double) { type = JsonType.Double; inst_double = (double)obj; return; } if (obj is int) { type = JsonType.Int; inst_int = (int)obj; return; } if (obj is long) { type = JsonType.Long; inst_long = (long)obj; return; } if (obj is string) { type = JsonType.String; inst_string = (string)obj; return; } throw new ArgumentException("Unable to wrap the given object with JsonData"); } public JsonData(string str) { type = JsonType.String; inst_string = str; } public static implicit operator JsonData(bool data) { return new JsonData(data); } public static implicit operator JsonData(double data) { return new JsonData(data); } public static implicit operator JsonData(int data) { return new JsonData(data); } public static implicit operator JsonData(long data) { return new JsonData(data); } public static implicit operator JsonData(string data) { return new JsonData(data); } public static explicit operator bool(JsonData data) { if (data.type != JsonType.Boolean) { throw new InvalidCastException("Instance of JsonData doesn't hold a double"); } return data.inst_boolean; } public static explicit operator double(JsonData data) { if (data.type != JsonType.Double) { throw new InvalidCastException("Instance of JsonData doesn't hold a double"); } return data.inst_double; } public static explicit operator int(JsonData data) { if (data.type != JsonType.Int && data.type != JsonType.Long) { throw new InvalidCastException("Instance of JsonData doesn't hold an int"); } if (data.type != JsonType.Int) { return (int)data.inst_long; } return data.inst_int; } public static explicit operator long(JsonData data) { if (data.type != JsonType.Long && data.type != JsonType.Int) { throw new InvalidCastException("Instance of JsonData doesn't hold a long"); } if (data.type != JsonType.Long) { return data.inst_int; } return data.inst_long; } public static explicit operator string(JsonData data) { if (data.type != JsonType.String) { throw new InvalidCastException("Instance of JsonData doesn't hold a string"); } return data.inst_string; } void ICollection.CopyTo(Array array, int index) { EnsureCollection().CopyTo(array, index); } void IDictionary.Add(object key, object value) { JsonData value2 = ToJsonData(value); EnsureDictionary().Add(key, value2); KeyValuePair item = new KeyValuePair((string)key, value2); object_list.Add(item); json = null; } void IDictionary.Clear() { EnsureDictionary().Clear(); object_list.Clear(); json = null; } bool IDictionary.Contains(object key) { return EnsureDictionary().Contains(key); } IDictionaryEnumerator IDictionary.GetEnumerator() { return ((IOrderedDictionary)this).GetEnumerator(); } void IDictionary.Remove(object key) { EnsureDictionary().Remove(key); for (int i = 0; i < object_list.Count; i++) { if (object_list[i].Key == (string)key) { object_list.RemoveAt(i); break; } } json = null; } IEnumerator IEnumerable.GetEnumerator() { return EnsureCollection().GetEnumerator(); } bool IJsonWrapper.GetBoolean() { if (type != JsonType.Boolean) { throw new InvalidOperationException("JsonData instance doesn't hold a boolean"); } return inst_boolean; } double IJsonWrapper.GetDouble() { if (type != JsonType.Double) { throw new InvalidOperationException("JsonData instance doesn't hold a double"); } return inst_double; } int IJsonWrapper.GetInt() { if (type != JsonType.Int) { throw new InvalidOperationException("JsonData instance doesn't hold an int"); } return inst_int; } long IJsonWrapper.GetLong() { if (type != JsonType.Long) { throw new InvalidOperationException("JsonData instance doesn't hold a long"); } return inst_long; } string IJsonWrapper.GetString() { if (type != JsonType.String) { throw new InvalidOperationException("JsonData instance doesn't hold a string"); } return inst_string; } void IJsonWrapper.SetBoolean(bool val) { type = JsonType.Boolean; inst_boolean = val; json = null; } void IJsonWrapper.SetDouble(double val) { type = JsonType.Double; inst_double = val; json = null; } void IJsonWrapper.SetInt(int val) { type = JsonType.Int; inst_int = val; json = null; } void IJsonWrapper.SetLong(long val) { type = JsonType.Long; inst_long = val; json = null; } void IJsonWrapper.SetString(string val) { type = JsonType.String; inst_string = val; json = null; } string IJsonWrapper.ToJson() { return ToJson(); } void IJsonWrapper.ToJson(JsonWriter writer) { ToJson(writer); } int IList.Add(object value) { return Add(value); } void IList.Clear() { EnsureList().Clear(); json = null; } bool IList.Contains(object value) { return EnsureList().Contains(value); } int IList.IndexOf(object value) { return EnsureList().IndexOf(value); } void IList.Insert(int index, object value) { EnsureList().Insert(index, value); json = null; } void IList.Remove(object value) { EnsureList().Remove(value); json = null; } void IList.RemoveAt(int index) { EnsureList().RemoveAt(index); json = null; } IDictionaryEnumerator IOrderedDictionary.GetEnumerator() { EnsureDictionary(); return new OrderedDictionaryEnumerator(object_list.GetEnumerator()); } void IOrderedDictionary.Insert(int idx, object key, object value) { string text = (string)key; JsonData value2 = (this[text] = ToJsonData(value)); KeyValuePair item = new KeyValuePair(text, value2); object_list.Insert(idx, item); } void IOrderedDictionary.RemoveAt(int idx) { EnsureDictionary(); inst_object.Remove(object_list[idx].Key); object_list.RemoveAt(idx); } private ICollection EnsureCollection() { if (type == JsonType.Array) { return (ICollection)inst_array; } if (type == JsonType.Object) { return (ICollection)inst_object; } throw new InvalidOperationException("The JsonData instance has to be initialized first"); } private IDictionary EnsureDictionary() { if (type == JsonType.Object) { return (IDictionary)inst_object; } if (type != 0) { throw new InvalidOperationException("Instance of JsonData is not a dictionary"); } type = JsonType.Object; inst_object = new Dictionary(); object_list = new List>(); return (IDictionary)inst_object; } private IList EnsureList() { if (type == JsonType.Array) { return (IList)inst_array; } if (type != 0) { throw new InvalidOperationException("Instance of JsonData is not a list"); } type = JsonType.Array; inst_array = new List(); return (IList)inst_array; } private JsonData ToJsonData(object obj) { if (obj == null) { return null; } if (obj is JsonData) { return (JsonData)obj; } return new JsonData(obj); } private static void WriteJson(IJsonWrapper obj, JsonWriter writer) { if (obj == null) { writer.Write(null); } else if (obj.IsString) { writer.Write(obj.GetString()); } else if (obj.IsBoolean) { writer.Write(obj.GetBoolean()); } else if (obj.IsDouble) { writer.Write(obj.GetDouble()); } else if (obj.IsInt) { writer.Write(obj.GetInt()); } else if (obj.IsLong) { writer.Write(obj.GetLong()); } else if (obj.IsArray) { writer.WriteArrayStart(); foreach (JsonData item in (IEnumerable)obj) { WriteJson(item, writer); } writer.WriteArrayEnd(); } else { if (!obj.IsObject) { return; } writer.WriteObjectStart(); foreach (DictionaryEntry item2 in (IDictionary)obj) { writer.WritePropertyName((string)item2.Key); WriteJson((JsonData)item2.Value, writer); } writer.WriteObjectEnd(); } } public int Add(object value) { JsonData value2 = ToJsonData(value); json = null; return EnsureList().Add(value2); } public bool Remove(object obj) { json = null; if (IsObject) { JsonData value = null; if (inst_object.TryGetValue((string)obj, out value)) { if (inst_object.Remove((string)obj)) { return object_list.Remove(new KeyValuePair((string)obj, value)); } return false; } throw new KeyNotFoundException("The specified key was not found in the JsonData object."); } if (IsArray) { return inst_array.Remove(ToJsonData(obj)); } throw new InvalidOperationException("Instance of JsonData is not an object or a list."); } public void Clear() { if (IsObject) { ((IDictionary)this).Clear(); } else if (IsArray) { ((IList)this).Clear(); } } public bool Equals(JsonData x) { if (x == null) { return false; } if (x.type != type && ((x.type != JsonType.Int && x.type != JsonType.Long) || (type != JsonType.Int && type != JsonType.Long))) { return false; } switch (type) { case JsonType.None: return true; case JsonType.Object: return inst_object.Equals(x.inst_object); case JsonType.Array: return inst_array.Equals(x.inst_array); case JsonType.String: return inst_string.Equals(x.inst_string); case JsonType.Int: if (x.IsLong) { if (x.inst_long < int.MinValue || x.inst_long > int.MaxValue) { return false; } return inst_int.Equals((int)x.inst_long); } return inst_int.Equals(x.inst_int); case JsonType.Long: if (x.IsInt) { if (inst_long < int.MinValue || inst_long > int.MaxValue) { return false; } return x.inst_int.Equals((int)inst_long); } return inst_long.Equals(x.inst_long); case JsonType.Double: return inst_double.Equals(x.inst_double); case JsonType.Boolean: return inst_boolean.Equals(x.inst_boolean); default: return false; } } public JsonType GetJsonType() { return type; } public void SetJsonType(JsonType type) { if (this.type != type) { switch (type) { case JsonType.Object: inst_object = new Dictionary(); object_list = new List>(); break; case JsonType.Array: inst_array = new List(); break; case JsonType.String: inst_string = null; break; case JsonType.Int: inst_int = 0; break; case JsonType.Long: inst_long = 0L; break; case JsonType.Double: inst_double = 0.0; break; case JsonType.Boolean: inst_boolean = false; break; } this.type = type; } } public string ToJson() { if (json != null) { return json; } StringWriter stringWriter = new StringWriter(); JsonWriter jsonWriter = new JsonWriter(stringWriter); jsonWriter.Validate = false; WriteJson(this, jsonWriter); json = stringWriter.ToString(); return json; } public void ToJson(JsonWriter writer) { bool validate = writer.Validate; writer.Validate = false; WriteJson(this, writer); writer.Validate = validate; } public override string ToString() { return type switch { JsonType.Array => "JsonData array", JsonType.Boolean => inst_boolean.ToString(), JsonType.Double => inst_double.ToString(), JsonType.Int => inst_int.ToString(), JsonType.Long => inst_long.ToString(), JsonType.Object => "JsonData object", JsonType.String => inst_string, _ => "Uninitialized JsonData", }; } } internal class OrderedDictionaryEnumerator : IDictionaryEnumerator, IEnumerator { private IEnumerator> list_enumerator; public object Current => Entry; public DictionaryEntry Entry { get { KeyValuePair current = list_enumerator.Current; return new DictionaryEntry(current.Key, current.Value); } } public object Key => list_enumerator.Current.Key; public object Value => list_enumerator.Current.Value; public OrderedDictionaryEnumerator(IEnumerator> enumerator) { list_enumerator = enumerator; } public bool MoveNext() { return list_enumerator.MoveNext(); } public void Reset() { list_enumerator.Reset(); } } internal class JsonException : ApplicationException { public JsonException() { } internal JsonException(ParserToken token) : base($"Invalid token '{token}' in input string") { } internal JsonException(ParserToken token, Exception inner_exception) : base($"Invalid token '{token}' in input string", inner_exception) { } internal JsonException(int c) : base($"Invalid character '{(char)c}' in input string") { } internal JsonException(int c, Exception inner_exception) : base($"Invalid character '{(char)c}' in input string", inner_exception) { } public JsonException(string message) : base(message) { } public JsonException(string message, Exception inner_exception) : base(message, inner_exception) { } } internal struct PropertyMetadata { public MemberInfo Info; public bool IsField; public Type Type; } internal struct ArrayMetadata { private Type element_type; private bool is_array; private bool is_list; public Type ElementType { get { if (element_type == null) { return typeof(JsonData); } return element_type; } set { element_type = value; } } public bool IsArray { get { return is_array; } set { is_array = value; } } public bool IsList { get { return is_list; } set { is_list = value; } } } internal struct ObjectMetadata { private Type element_type; private bool is_dictionary; private IDictionary properties; public Type ElementType { get { if (element_type == null) { return typeof(JsonData); } return element_type; } set { element_type = value; } } public bool IsDictionary { get { return is_dictionary; } set { is_dictionary = value; } } public IDictionary Properties { get { return properties; } set { properties = value; } } } internal delegate void ExporterFunc(object obj, JsonWriter writer); public delegate void ExporterFunc(T obj, JsonWriter writer); internal delegate object ImporterFunc(object input); public delegate TValue ImporterFunc(TJson input); internal delegate IJsonWrapper WrapperFactory(); internal class JsonMapper { private static readonly int max_nesting_depth; private static readonly IFormatProvider datetime_format; private static readonly IDictionary base_exporters_table; private static readonly IDictionary custom_exporters_table; private static readonly IDictionary> base_importers_table; private static readonly IDictionary> custom_importers_table; private static readonly IDictionary array_metadata; private static readonly object array_metadata_lock; private static readonly IDictionary> conv_ops; private static readonly object conv_ops_lock; private static readonly IDictionary object_metadata; private static readonly object object_metadata_lock; private static readonly IDictionary> type_properties; private static readonly object type_properties_lock; private static readonly JsonWriter static_writer; private static readonly object static_writer_lock; static JsonMapper() { array_metadata_lock = new object(); conv_ops_lock = new object(); object_metadata_lock = new object(); type_properties_lock = new object(); static_writer_lock = new object(); max_nesting_depth = 100; array_metadata = new Dictionary(); conv_ops = new Dictionary>(); object_metadata = new Dictionary(); type_properties = new Dictionary>(); static_writer = new JsonWriter(); datetime_format = DateTimeFormatInfo.InvariantInfo; base_exporters_table = new Dictionary(); custom_exporters_table = new Dictionary(); base_importers_table = new Dictionary>(); custom_importers_table = new Dictionary>(); RegisterBaseExporters(); RegisterBaseImporters(); } private static void AddArrayMetadata(Type type) { if (array_metadata.ContainsKey(type)) { return; } ArrayMetadata value = default(ArrayMetadata); value.IsArray = type.IsArray; if (type.GetInterface("System.Collections.IList") != null) { value.IsList = true; } PropertyInfo[] properties = type.GetProperties(); foreach (PropertyInfo propertyInfo in properties) { if (!(propertyInfo.Name != "Item")) { ParameterInfo[] indexParameters = propertyInfo.GetIndexParameters(); if (indexParameters.Length == 1 && indexParameters[0].ParameterType == typeof(int)) { value.ElementType = propertyInfo.PropertyType; } } } lock (array_metadata_lock) { try { array_metadata.Add(type, value); } catch (ArgumentException) { } } } private static void AddObjectMetadata(Type type) { if (object_metadata.ContainsKey(type)) { return; } ObjectMetadata value = default(ObjectMetadata); if (type.GetInterface("System.Collections.IDictionary") != null) { value.IsDictionary = true; } value.Properties = new Dictionary(); PropertyInfo[] properties = type.GetProperties(); foreach (PropertyInfo propertyInfo in properties) { if (propertyInfo.Name == "Item") { ParameterInfo[] indexParameters = propertyInfo.GetIndexParameters(); if (indexParameters.Length == 1 && indexParameters[0].ParameterType == typeof(string)) { value.ElementType = propertyInfo.PropertyType; } } else { PropertyMetadata value2 = default(PropertyMetadata); value2.Info = propertyInfo; value2.Type = propertyInfo.PropertyType; value.Properties.Add(propertyInfo.Name, value2); } } FieldInfo[] fields = type.GetFields(); foreach (FieldInfo fieldInfo in fields) { PropertyMetadata value3 = default(PropertyMetadata); value3.Info = fieldInfo; value3.IsField = true; value3.Type = fieldInfo.FieldType; value.Properties.Add(fieldInfo.Name, value3); } lock (object_metadata_lock) { try { object_metadata.Add(type, value); } catch (ArgumentException) { } } } private static void AddTypeProperties(Type type) { if (type_properties.ContainsKey(type)) { return; } IList list = new List(); PropertyInfo[] properties = type.GetProperties(); foreach (PropertyInfo propertyInfo in properties) { if (!(propertyInfo.Name == "Item")) { PropertyMetadata item = default(PropertyMetadata); item.Info = propertyInfo; item.IsField = false; list.Add(item); } } FieldInfo[] fields = type.GetFields(); foreach (FieldInfo info in fields) { PropertyMetadata item2 = default(PropertyMetadata); item2.Info = info; item2.IsField = true; list.Add(item2); } lock (type_properties_lock) { try { type_properties.Add(type, list); } catch (ArgumentException) { } } } private static MethodInfo GetConvOp(Type t1, Type t2) { lock (conv_ops_lock) { if (!conv_ops.ContainsKey(t1)) { conv_ops.Add(t1, new Dictionary()); } } if (conv_ops[t1].ContainsKey(t2)) { return conv_ops[t1][t2]; } MethodInfo method = t1.GetMethod("op_Implicit", new Type[1] { t2 }); lock (conv_ops_lock) { try { conv_ops[t1].Add(t2, method); return method; } catch (ArgumentException) { return conv_ops[t1][t2]; } } } private static object ReadValue(Type inst_type, JsonReader reader) { reader.Read(); if (reader.Token == JsonToken.ArrayEnd) { return null; } Type underlyingType = Nullable.GetUnderlyingType(inst_type); Type type = underlyingType ?? inst_type; if (reader.Token == JsonToken.Null) { if (inst_type.IsClass || underlyingType != null) { return null; } throw new JsonException($"Can't assign null to an instance of type {inst_type}"); } if (reader.Token == JsonToken.Double || reader.Token == JsonToken.Int || reader.Token == JsonToken.Long || reader.Token == JsonToken.String || reader.Token == JsonToken.Boolean) { Type type2 = reader.Value.GetType(); if (type.IsAssignableFrom(type2)) { return reader.Value; } if (custom_importers_table.ContainsKey(type2) && custom_importers_table[type2].ContainsKey(type)) { return custom_importers_table[type2][type](reader.Value); } if (base_importers_table.ContainsKey(type2) && base_importers_table[type2].ContainsKey(type)) { return base_importers_table[type2][type](reader.Value); } if (type.IsEnum) { return Enum.ToObject(type, reader.Value); } MethodInfo convOp = GetConvOp(type, type2); if (convOp != null) { return convOp.Invoke(null, new object[1] { reader.Value }); } throw new JsonException($"Can't assign value '{reader.Value}' (type {type2}) to type {inst_type}"); } object obj = null; if (reader.Token == JsonToken.ArrayStart) { AddArrayMetadata(inst_type); ArrayMetadata arrayMetadata = array_metadata[inst_type]; if (!arrayMetadata.IsArray && !arrayMetadata.IsList) { throw new JsonException($"Type {inst_type} can't act as an array"); } IList list; Type elementType; if (!arrayMetadata.IsArray) { list = (IList)Activator.CreateInstance(inst_type); elementType = arrayMetadata.ElementType; } else { list = new ArrayList(); elementType = inst_type.GetElementType(); } list.Clear(); while (true) { object obj2 = ReadValue(elementType, reader); if (obj2 == null && reader.Token == JsonToken.ArrayEnd) { break; } list.Add(obj2); } if (arrayMetadata.IsArray) { int count = list.Count; obj = Array.CreateInstance(elementType, count); for (int i = 0; i < count; i++) { ((Array)obj).SetValue(list[i], i); } } else { obj = list; } } else if (reader.Token == JsonToken.ObjectStart) { AddObjectMetadata(type); ObjectMetadata objectMetadata = object_metadata[type]; obj = Activator.CreateInstance(type); while (true) { reader.Read(); if (reader.Token == JsonToken.ObjectEnd) { break; } string text = (string)reader.Value; if (objectMetadata.Properties.ContainsKey(text)) { PropertyMetadata propertyMetadata = objectMetadata.Properties[text]; if (propertyMetadata.IsField) { ((FieldInfo)propertyMetadata.Info).SetValue(obj, ReadValue(propertyMetadata.Type, reader)); continue; } PropertyInfo propertyInfo = (PropertyInfo)propertyMetadata.Info; if (propertyInfo.CanWrite) { propertyInfo.SetValue(obj, ReadValue(propertyMetadata.Type, reader), null); } else { ReadValue(propertyMetadata.Type, reader); } } else if (!objectMetadata.IsDictionary) { if (!reader.SkipNonMembers) { throw new JsonException($"The type {inst_type} doesn't have the property '{text}'"); } ReadSkip(reader); } else { ((IDictionary)obj).Add(text, ReadValue(objectMetadata.ElementType, reader)); } } } return obj; } private static IJsonWrapper ReadValue(WrapperFactory factory, JsonReader reader) { reader.Read(); if (reader.Token == JsonToken.ArrayEnd || reader.Token == JsonToken.Null) { return null; } IJsonWrapper jsonWrapper = factory(); if (reader.Token == JsonToken.String) { jsonWrapper.SetString((string)reader.Value); return jsonWrapper; } if (reader.Token == JsonToken.Double) { jsonWrapper.SetDouble((double)reader.Value); return jsonWrapper; } if (reader.Token == JsonToken.Int) { jsonWrapper.SetInt((int)reader.Value); return jsonWrapper; } if (reader.Token == JsonToken.Long) { jsonWrapper.SetLong((long)reader.Value); return jsonWrapper; } if (reader.Token == JsonToken.Boolean) { jsonWrapper.SetBoolean((bool)reader.Value); return jsonWrapper; } if (reader.Token == JsonToken.ArrayStart) { jsonWrapper.SetJsonType(JsonType.Array); while (true) { IJsonWrapper jsonWrapper2 = ReadValue(factory, reader); if (jsonWrapper2 == null && reader.Token == JsonToken.ArrayEnd) { break; } jsonWrapper.Add(jsonWrapper2); } } else if (reader.Token == JsonToken.ObjectStart) { jsonWrapper.SetJsonType(JsonType.Object); while (true) { reader.Read(); if (reader.Token == JsonToken.ObjectEnd) { break; } string key = (string)reader.Value; jsonWrapper[key] = ReadValue(factory, reader); } } return jsonWrapper; } private static void ReadSkip(JsonReader reader) { ToWrapper(() => new JsonMockWrapper(), reader); } private static void RegisterBaseExporters() { base_exporters_table[typeof(byte)] = delegate(object obj, JsonWriter writer) { writer.Write(Convert.ToInt32((byte)obj)); }; base_exporters_table[typeof(char)] = delegate(object obj, JsonWriter writer) { writer.Write(Convert.ToString((char)obj)); }; base_exporters_table[typeof(DateTime)] = delegate(object obj, JsonWriter writer) { writer.Write(Convert.ToString((DateTime)obj, datetime_format)); }; base_exporters_table[typeof(decimal)] = delegate(object obj, JsonWriter writer) { writer.Write((decimal)obj); }; base_exporters_table[typeof(sbyte)] = delegate(object obj, JsonWriter writer) { writer.Write(Convert.ToInt32((sbyte)obj)); }; base_exporters_table[typeof(short)] = delegate(object obj, JsonWriter writer) { writer.Write(Convert.ToInt32((short)obj)); }; base_exporters_table[typeof(ushort)] = delegate(object obj, JsonWriter writer) { writer.Write(Convert.ToInt32((ushort)obj)); }; base_exporters_table[typeof(uint)] = delegate(object obj, JsonWriter writer) { writer.Write(Convert.ToUInt64((uint)obj)); }; base_exporters_table[typeof(ulong)] = delegate(object obj, JsonWriter writer) { writer.Write((ulong)obj); }; base_exporters_table[typeof(DateTimeOffset)] = delegate(object obj, JsonWriter writer) { writer.Write(((DateTimeOffset)obj).ToString("yyyy-MM-ddTHH:mm:ss.fffffffzzz", datetime_format)); }; } private static void RegisterBaseImporters() { ImporterFunc importer = (object input) => Convert.ToByte((int)input); RegisterImporter(base_importers_table, typeof(int), typeof(byte), importer); importer = (object input) => Convert.ToUInt64((int)input); RegisterImporter(base_importers_table, typeof(int), typeof(ulong), importer); importer = (object input) => Convert.ToInt64((int)input); RegisterImporter(base_importers_table, typeof(int), typeof(long), importer); importer = (object input) => Convert.ToSByte((int)input); RegisterImporter(base_importers_table, typeof(int), typeof(sbyte), importer); importer = (object input) => Convert.ToInt16((int)input); RegisterImporter(base_importers_table, typeof(int), typeof(short), importer); importer = (object input) => Convert.ToUInt16((int)input); RegisterImporter(base_importers_table, typeof(int), typeof(ushort), importer); importer = (object input) => Convert.ToUInt32((int)input); RegisterImporter(base_importers_table, typeof(int), typeof(uint), importer); importer = (object input) => Convert.ToSingle((int)input); RegisterImporter(base_importers_table, typeof(int), typeof(float), importer); importer = (object input) => Convert.ToDouble((int)input); RegisterImporter(base_importers_table, typeof(int), typeof(double), importer); importer = (object input) => Convert.ToDecimal((double)input); RegisterImporter(base_importers_table, typeof(double), typeof(decimal), importer); importer = (object input) => Convert.ToSingle((double)input); RegisterImporter(base_importers_table, typeof(double), typeof(float), importer); importer = (object input) => Convert.ToUInt32((long)input); RegisterImporter(base_importers_table, typeof(long), typeof(uint), importer); importer = (object input) => Convert.ToChar((string)input); RegisterImporter(base_importers_table, typeof(string), typeof(char), importer); importer = (object input) => Convert.ToDateTime((string)input, datetime_format); RegisterImporter(base_importers_table, typeof(string), typeof(DateTime), importer); importer = (object input) => DateTimeOffset.Parse((string)input, datetime_format); RegisterImporter(base_importers_table, typeof(string), typeof(DateTimeOffset), importer); } private static void RegisterImporter(IDictionary> table, Type json_type, Type value_type, ImporterFunc importer) { if (!table.ContainsKey(json_type)) { table.Add(json_type, new Dictionary()); } table[json_type][value_type] = importer; } private static void WriteValue(object obj, JsonWriter writer, bool writer_is_private, int depth) { if (depth > max_nesting_depth) { throw new JsonException($"Max allowed object depth reached while trying to export from type {obj.GetType()}"); } if (obj == null) { writer.Write(null); return; } if (obj is IJsonWrapper) { if (writer_is_private) { writer.TextWriter.Write(((IJsonWrapper)obj).ToJson()); } else { ((IJsonWrapper)obj).ToJson(writer); } return; } if (obj is string) { writer.Write((string)obj); return; } if (obj is double) { writer.Write((double)obj); return; } if (obj is float) { writer.Write((float)obj); return; } if (obj is int) { writer.Write((int)obj); return; } if (obj is bool) { writer.Write((bool)obj); return; } if (obj is long) { writer.Write((long)obj); return; } if (obj is Array) { writer.WriteArrayStart(); foreach (object item in (Array)obj) { WriteValue(item, writer, writer_is_private, depth + 1); } writer.WriteArrayEnd(); return; } if (obj is IList) { writer.WriteArrayStart(); foreach (object item2 in (IList)obj) { WriteValue(item2, writer, writer_is_private, depth + 1); } writer.WriteArrayEnd(); return; } if (obj is IDictionary dictionary) { writer.WriteObjectStart(); foreach (DictionaryEntry item3 in dictionary) { string property_name = ((item3.Key is string text) ? text : Convert.ToString(item3.Key, CultureInfo.InvariantCulture)); writer.WritePropertyName(property_name); WriteValue(item3.Value, writer, writer_is_private, depth + 1); } writer.WriteObjectEnd(); return; } Type type = obj.GetType(); if (custom_exporters_table.ContainsKey(type)) { custom_exporters_table[type](obj, writer); return; } if (base_exporters_table.ContainsKey(type)) { base_exporters_table[type](obj, writer); return; } if (obj is Enum) { Type underlyingType = Enum.GetUnderlyingType(type); if (underlyingType == typeof(long)) { writer.Write((long)obj); } else if (underlyingType == typeof(uint)) { writer.Write((uint)obj); } else if (underlyingType == typeof(ulong)) { writer.Write((ulong)obj); } else if (underlyingType == typeof(ushort)) { writer.Write((ushort)obj); } else if (underlyingType == typeof(short)) { writer.Write((short)obj); } else if (underlyingType == typeof(byte)) { writer.Write((byte)obj); } else if (underlyingType == typeof(sbyte)) { writer.Write((sbyte)obj); } else { writer.Write((int)obj); } return; } AddTypeProperties(type); IList list = type_properties[type]; writer.WriteObjectStart(); foreach (PropertyMetadata item4 in list) { if (item4.IsField) { writer.WritePropertyName(item4.Info.Name); WriteValue(((FieldInfo)item4.Info).GetValue(obj), writer, writer_is_private, depth + 1); continue; } PropertyInfo propertyInfo = (PropertyInfo)item4.Info; if (propertyInfo.CanRead) { writer.WritePropertyName(item4.Info.Name); WriteValue(propertyInfo.GetValue(obj, null), writer, writer_is_private, depth + 1); } } writer.WriteObjectEnd(); } public static string ToJson(object obj) { lock (static_writer_lock) { static_writer.Reset(); WriteValue(obj, static_writer, writer_is_private: true, 0); return static_writer.ToString(); } } public static void ToJson(object obj, JsonWriter writer) { WriteValue(obj, writer, writer_is_private: false, 0); } public static JsonData ToObject(JsonReader reader) { return (JsonData)ToWrapper(() => new JsonData(), reader); } public static JsonData ToObject(TextReader reader) { JsonReader reader2 = new JsonReader(reader); return (JsonData)ToWrapper(() => new JsonData(), reader2); } public static JsonData ToObject(string json) { return (JsonData)ToWrapper(() => new JsonData(), json); } public static T ToObject(JsonReader reader) { return (T)ReadValue(typeof(T), reader); } public static T ToObject(TextReader reader) { JsonReader reader2 = new JsonReader(reader); return (T)ReadValue(typeof(T), reader2); } public static T ToObject(string json) { JsonReader reader = new JsonReader(json); return (T)ReadValue(typeof(T), reader); } public static object ToObject(string json, Type ConvertType) { JsonReader reader = new JsonReader(json); return ReadValue(ConvertType, reader); } public static IJsonWrapper ToWrapper(WrapperFactory factory, JsonReader reader) { return ReadValue(factory, reader); } public static IJsonWrapper ToWrapper(WrapperFactory factory, string json) { JsonReader reader = new JsonReader(json); return ReadValue(factory, reader); } public static void RegisterExporter(ExporterFunc exporter) { ExporterFunc value = delegate(object obj, JsonWriter writer) { exporter((T)obj, writer); }; custom_exporters_table[typeof(T)] = value; } public static void RegisterImporter(ImporterFunc importer) { ImporterFunc importer2 = (object input) => importer((TJson)input); RegisterImporter(custom_importers_table, typeof(TJson), typeof(TValue), importer2); } public static void UnregisterExporters() { custom_exporters_table.Clear(); } public static void UnregisterImporters() { custom_importers_table.Clear(); } } internal class JsonMockWrapper : IJsonWrapper, IList, ICollection, IEnumerable, IOrderedDictionary, IDictionary { public bool IsArray => false; public bool IsBoolean => false; public bool IsDouble => false; public bool IsInt => false; public bool IsLong => false; public bool IsObject => false; public bool IsString => false; bool IList.IsFixedSize => true; bool IList.IsReadOnly => true; object IList.this[int index] { get { return null; } set { } } int ICollection.Count => 0; bool ICollection.IsSynchronized => false; object ICollection.SyncRoot => null; bool IDictionary.IsFixedSize => true; bool IDictionary.IsReadOnly => true; ICollection IDictionary.Keys => null; ICollection IDictionary.Values => null; object IDictionary.this[object key] { get { return null; } set { } } object IOrderedDictionary.this[int idx] { get { return null; } set { } } public bool GetBoolean() { return false; } public double GetDouble() { return 0.0; } public int GetInt() { return 0; } public JsonType GetJsonType() { return JsonType.None; } public long GetLong() { return 0L; } public string GetString() { return ""; } public void SetBoolean(bool val) { } public void SetDouble(double val) { } public void SetInt(int val) { } public void SetJsonType(JsonType type) { } public void SetLong(long val) { } public void SetString(string val) { } public string ToJson() { return ""; } public void ToJson(JsonWriter writer) { } int IList.Add(object value) { return 0; } void IList.Clear() { } bool IList.Contains(object value) { return false; } int IList.IndexOf(object value) { return -1; } void IList.Insert(int i, object v) { } void IList.Remove(object value) { } void IList.RemoveAt(int index) { } void ICollection.CopyTo(Array array, int index) { } IEnumerator IEnumerable.GetEnumerator() { return null; } void IDictionary.Add(object k, object v) { } void IDictionary.Clear() { } bool IDictionary.Contains(object key) { return false; } void IDictionary.Remove(object key) { } IDictionaryEnumerator IDictionary.GetEnumerator() { return null; } IDictionaryEnumerator IOrderedDictionary.GetEnumerator() { return null; } void IOrderedDictionary.Insert(int i, object k, object v) { } void IOrderedDictionary.RemoveAt(int i) { } } internal enum JsonToken { None, ObjectStart, PropertyName, ObjectEnd, ArrayStart, ArrayEnd, Int, Long, Double, String, Boolean, Null } internal class JsonReader { private static readonly IDictionary> parse_table; private Stack automaton_stack; private int current_input; private int current_symbol; private bool end_of_json; private bool end_of_input; private Lexer lexer; private bool parser_in_string; private bool parser_return; private bool read_started; private TextReader reader; private bool reader_is_owned; private bool skip_non_members; private object token_value; private JsonToken token; public bool AllowComments { get { return lexer.AllowComments; } set { lexer.AllowComments = value; } } public bool AllowSingleQuotedStrings { get { return lexer.AllowSingleQuotedStrings; } set { lexer.AllowSingleQuotedStrings = value; } } public bool SkipNonMembers { get { return skip_non_members; } set { skip_non_members = value; } } public bool EndOfInput => end_of_input; public bool EndOfJson => end_of_json; public JsonToken Token => token; public object Value => token_value; static JsonReader() { parse_table = PopulateParseTable(); } public JsonReader(string json_text) : this(new StringReader(json_text), owned: true) { } public JsonReader(TextReader reader) : this(reader, owned: false) { } private JsonReader(TextReader reader, bool owned) { if (reader == null) { throw new ArgumentNullException("reader"); } parser_in_string = false; parser_return = false; read_started = false; automaton_stack = new Stack(); automaton_stack.Push(65553); automaton_stack.Push(65543); lexer = new Lexer(reader); end_of_input = false; end_of_json = false; skip_non_members = true; this.reader = reader; reader_is_owned = owned; } private static IDictionary> PopulateParseTable() { IDictionary> result = new Dictionary>(); TableAddRow(result, ParserToken.Array); TableAddCol(result, ParserToken.Array, 91, 91, 65549); TableAddRow(result, ParserToken.ArrayPrime); TableAddCol(result, ParserToken.ArrayPrime, 34, 65550, 65551, 93); TableAddCol(result, ParserToken.ArrayPrime, 91, 65550, 65551, 93); TableAddCol(result, ParserToken.ArrayPrime, 93, 93); TableAddCol(result, ParserToken.ArrayPrime, 123, 65550, 65551, 93); TableAddCol(result, ParserToken.ArrayPrime, 65537, 65550, 65551, 93); TableAddCol(result, ParserToken.ArrayPrime, 65538, 65550, 65551, 93); TableAddCol(result, ParserToken.ArrayPrime, 65539, 65550, 65551, 93); TableAddCol(result, ParserToken.ArrayPrime, 65540, 65550, 65551, 93); TableAddRow(result, ParserToken.Object); TableAddCol(result, ParserToken.Object, 123, 123, 65545); TableAddRow(result, ParserToken.ObjectPrime); TableAddCol(result, ParserToken.ObjectPrime, 34, 65546, 65547, 125); TableAddCol(result, ParserToken.ObjectPrime, 125, 125); TableAddRow(result, ParserToken.Pair); TableAddCol(result, ParserToken.Pair, 34, 65552, 58, 65550); TableAddRow(result, ParserToken.PairRest); TableAddCol(result, ParserToken.PairRest, 44, 44, 65546, 65547); TableAddCol(result, ParserToken.PairRest, 125, 65554); TableAddRow(result, ParserToken.String); TableAddCol(result, ParserToken.String, 34, 34, 65541, 34); TableAddRow(result, ParserToken.Text); TableAddCol(result, ParserToken.Text, 91, 65548); TableAddCol(result, ParserToken.Text, 123, 65544); TableAddRow(result, ParserToken.Value); TableAddCol(result, ParserToken.Value, 34, 65552); TableAddCol(result, ParserToken.Value, 91, 65548); TableAddCol(result, ParserToken.Value, 123, 65544); TableAddCol(result, ParserToken.Value, 65537, 65537); TableAddCol(result, ParserToken.Value, 65538, 65538); TableAddCol(result, ParserToken.Value, 65539, 65539); TableAddCol(result, ParserToken.Value, 65540, 65540); TableAddRow(result, ParserToken.ValueRest); TableAddCol(result, ParserToken.ValueRest, 44, 44, 65550, 65551); TableAddCol(result, ParserToken.ValueRest, 93, 65554); return result; } private static void TableAddCol(IDictionary> parse_table, ParserToken row, int col, params int[] symbols) { parse_table[(int)row].Add(col, symbols); } private static void TableAddRow(IDictionary> parse_table, ParserToken rule) { parse_table.Add((int)rule, new Dictionary()); } private void ProcessNumber(string number) { int result2; long result3; ulong result4; if ((number.IndexOf('.') != -1 || number.IndexOf('e') != -1 || number.IndexOf('E') != -1) && double.TryParse(number, NumberStyles.Any, CultureInfo.InvariantCulture, out var result)) { token = JsonToken.Double; token_value = result; } else if (int.TryParse(number, NumberStyles.Integer, CultureInfo.InvariantCulture, out result2)) { token = JsonToken.Int; token_value = result2; } else if (long.TryParse(number, NumberStyles.Integer, CultureInfo.InvariantCulture, out result3)) { token = JsonToken.Long; token_value = result3; } else if (ulong.TryParse(number, NumberStyles.Integer, CultureInfo.InvariantCulture, out result4)) { token = JsonToken.Long; token_value = result4; } else { token = JsonToken.Int; token_value = 0; } } private void ProcessSymbol() { if (current_symbol == 91) { token = JsonToken.ArrayStart; parser_return = true; } else if (current_symbol == 93) { token = JsonToken.ArrayEnd; parser_return = true; } else if (current_symbol == 123) { token = JsonToken.ObjectStart; parser_return = true; } else if (current_symbol == 125) { token = JsonToken.ObjectEnd; parser_return = true; } else if (current_symbol == 34) { if (parser_in_string) { parser_in_string = false; parser_return = true; return; } if (token == JsonToken.None) { token = JsonToken.String; } parser_in_string = true; } else if (current_symbol == 65541) { token_value = lexer.StringValue; } else if (current_symbol == 65539) { token = JsonToken.Boolean; token_value = false; parser_return = true; } else if (current_symbol == 65540) { token = JsonToken.Null; parser_return = true; } else if (current_symbol == 65537) { ProcessNumber(lexer.StringValue); parser_return = true; } else if (current_symbol == 65546) { token = JsonToken.PropertyName; } else if (current_symbol == 65538) { token = JsonToken.Boolean; token_value = true; parser_return = true; } } private bool ReadToken() { if (end_of_input) { return false; } lexer.NextToken(); if (lexer.EndOfInput) { Close(); return false; } current_input = lexer.Token; return true; } public void Close() { if (end_of_input) { return; } end_of_input = true; end_of_json = true; if (reader_is_owned) { using (reader) { } } reader = null; } public bool Read() { if (end_of_input) { return false; } if (end_of_json) { end_of_json = false; automaton_stack.Clear(); automaton_stack.Push(65553); automaton_stack.Push(65543); } parser_in_string = false; parser_return = false; token = JsonToken.None; token_value = null; if (!read_started) { read_started = true; if (!ReadToken()) { return false; } } while (true) { if (parser_return) { if (automaton_stack.Peek() == 65553) { end_of_json = true; } return true; } current_symbol = automaton_stack.Pop(); ProcessSymbol(); if (current_symbol == current_input) { if (!ReadToken()) { break; } continue; } int[] array; try { array = parse_table[current_symbol][current_input]; } catch (KeyNotFoundException inner_exception) { throw new JsonException((ParserToken)current_input, inner_exception); } if (array[0] != 65554) { for (int num = array.Length - 1; num >= 0; num--) { automaton_stack.Push(array[num]); } } } if (automaton_stack.Peek() != 65553) { throw new JsonException("Input doesn't evaluate to proper JSON text"); } if (parser_return) { return true; } return false; } } internal enum Condition { InArray, InObject, NotAProperty, Property, Value } internal class WriterContext { public int Count; public bool InArray; public bool InObject; public bool ExpectingValue; public int Padding; } public class JsonWriter { private static readonly NumberFormatInfo number_format; private WriterContext context; private Stack ctx_stack; private bool has_reached_end; private char[] hex_seq; private int indentation; private int indent_value; private StringBuilder inst_string_builder; private bool pretty_print; private bool validate; private bool lower_case_properties; private TextWriter writer; public int IndentValue { get { return indent_value; } set { indentation = indentation / indent_value * value; indent_value = value; } } public bool PrettyPrint { get { return pretty_print; } set { pretty_print = value; } } public TextWriter TextWriter => writer; public bool Validate { get { return validate; } set { validate = value; } } public bool LowerCaseProperties { get { return lower_case_properties; } set { lower_case_properties = value; } } static JsonWriter() { number_format = NumberFormatInfo.InvariantInfo; } public JsonWriter() { inst_string_builder = new StringBuilder(); writer = new StringWriter(inst_string_builder); Init(); } public JsonWriter(StringBuilder sb) : this(new StringWriter(sb)) { } public JsonWriter(TextWriter writer) { if (writer == null) { throw new ArgumentNullException("writer"); } this.writer = writer; Init(); } private void DoValidation(Condition cond) { if (!context.ExpectingValue) { context.Count++; } if (!validate) { return; } if (has_reached_end) { throw new JsonException("A complete JSON symbol has already been written"); } switch (cond) { case Condition.InArray: if (!context.InArray) { throw new JsonException("Can't close an array here"); } break; case Condition.InObject: if (!context.InObject || context.ExpectingValue) { throw new JsonException("Can't close an object here"); } break; case Condition.NotAProperty: if (context.InObject && !context.ExpectingValue) { throw new JsonException("Expected a property"); } break; case Condition.Property: if (!context.InObject || context.ExpectingValue) { throw new JsonException("Can't add a property here"); } break; case Condition.Value: if (!context.InArray && (!context.InObject || !context.ExpectingValue)) { throw new JsonException("Can't add a value here"); } break; } } private void Init() { has_reached_end = false; hex_seq = new char[4]; indentation = 0; indent_value = 4; pretty_print = false; validate = true; lower_case_properties = false; ctx_stack = new Stack(); context = new WriterContext(); ctx_stack.Push(context); } private static void IntToHex(int n, char[] hex) { for (int i = 0; i < 4; i++) { int num = n % 16; if (num < 10) { hex[3 - i] = (char)(48 + num); } else { hex[3 - i] = (char)(65 + (num - 10)); } n >>= 4; } } private void Indent() { if (pretty_print) { indentation += indent_value; } } private void Put(string str) { if (pretty_print && !context.ExpectingValue) { for (int i = 0; i < indentation; i++) { writer.Write(' '); } } writer.Write(str); } private void PutNewline() { PutNewline(add_comma: true); } private void PutNewline(bool add_comma) { if (add_comma && !context.ExpectingValue && context.Count > 1) { writer.Write(','); } if (pretty_print && !context.ExpectingValue) { writer.Write(Environment.NewLine); } } private void PutString(string str) { Put(string.Empty); writer.Write('"'); int length = str.Length; for (int i = 0; i < length; i++) { switch (str[i]) { case '\n': writer.Write("\\n"); continue; case '\r': writer.Write("\\r"); continue; case '\t': writer.Write("\\t"); continue; case '"': case '\\': writer.Write('\\'); writer.Write(str[i]); continue; case '\f': writer.Write("\\f"); continue; case '\b': writer.Write("\\b"); continue; } if (str[i] >= ' ' && str[i] <= '~') { writer.Write(str[i]); continue; } IntToHex(str[i], hex_seq); writer.Write("\\u"); writer.Write(hex_seq); } writer.Write('"'); } private void Unindent() { if (pretty_print) { indentation -= indent_value; } } public override string ToString() { if (inst_string_builder == null) { return string.Empty; } return inst_string_builder.ToString(); } public void Reset() { has_reached_end = false; ctx_stack.Clear(); context = new WriterContext(); ctx_stack.Push(context); if (inst_string_builder != null) { inst_string_builder.Remove(0, inst_string_builder.Length); } } public void Write(bool boolean) { DoValidation(Condition.Value); PutNewline(); Put(boolean ? "true" : "false"); context.ExpectingValue = false; } public void Write(decimal number) { DoValidation(Condition.Value); PutNewline(); Put(Convert.ToString(number, number_format)); context.ExpectingValue = false; } public void Write(double number) { DoValidation(Condition.Value); PutNewline(); string text = Convert.ToString(number, number_format); Put(text); if (text.IndexOf('.') == -1 && text.IndexOf('E') == -1) { writer.Write(".0"); } context.ExpectingValue = false; } public void Write(float number) { DoValidation(Condition.Value); PutNewline(); string str = Convert.ToString(number, number_format); Put(str); context.ExpectingValue = false; } public void Write(int number) { DoValidation(Condition.Value); PutNewline(); Put(Convert.ToString(number, number_format)); context.ExpectingValue = false; } public void Write(long number) { DoValidation(Condition.Value); PutNewline(); Put(Convert.ToString(number, number_format)); context.ExpectingValue = false; } public void Write(string str) { DoValidation(Condition.Value); PutNewline(); if (str == null) { Put("null"); } else { PutString(str); } context.ExpectingValue = false; } [CLSCompliant(false)] public void Write(ulong number) { DoValidation(Condition.Value); PutNewline(); Put(Convert.ToString(number, number_format)); context.ExpectingValue = false; } public void WriteArrayEnd() { DoValidation(Condition.InArray); PutNewline(add_comma: false); ctx_stack.Pop(); if (ctx_stack.Count == 1) { has_reached_end = true; } else { context = ctx_stack.Peek(); context.ExpectingValue = false; } Unindent(); Put("]"); } public void WriteArrayStart() { DoValidation(Condition.NotAProperty); PutNewline(); Put("["); context = new WriterContext(); context.InArray = true; ctx_stack.Push(context); Indent(); } public void WriteObjectEnd() { DoValidation(Condition.InObject); PutNewline(add_comma: false); ctx_stack.Pop(); if (ctx_stack.Count == 1) { has_reached_end = true; } else { context = ctx_stack.Peek(); context.ExpectingValue = false; } Unindent(); Put("}"); } public void WriteObjectStart() { DoValidation(Condition.NotAProperty); PutNewline(); Put("{"); context = new WriterContext(); context.InObject = true; ctx_stack.Push(context); Indent(); } public void WritePropertyName(string property_name) { DoValidation(Condition.Property); PutNewline(); string text = ((property_name == null || !lower_case_properties) ? property_name : property_name.ToLowerInvariant()); PutString(text); if (pretty_print) { if (text.Length > context.Padding) { context.Padding = text.Length; } for (int num = context.Padding - text.Length; num >= 0; num--) { writer.Write(' '); } writer.Write(": "); } else { writer.Write(':'); } context.ExpectingValue = true; } } internal class FsmContext { public bool Return; public int NextState; public Lexer L; public int StateStack; } internal class Lexer { private delegate bool StateHandler(FsmContext ctx); private static readonly int[] fsm_return_table; private static readonly StateHandler[] fsm_handler_table; private bool allow_comments; private bool allow_single_quoted_strings; private bool end_of_input; private FsmContext fsm_context; private int input_buffer; private int input_char; private TextReader reader; private int state; private StringBuilder string_buffer; private string string_value; private int token; private int unichar; public bool AllowComments { get { return allow_comments; } set { allow_comments = value; } } public bool AllowSingleQuotedStrings { get { return allow_single_quoted_strings; } set { allow_single_quoted_strings = value; } } public bool EndOfInput => end_of_input; public int Token => token; public string StringValue => string_value; static Lexer() { PopulateFsmTables(out fsm_handler_table, out fsm_return_table); } public Lexer(TextReader reader) { allow_comments = true; allow_single_quoted_strings = true; input_buffer = 0; string_buffer = new StringBuilder(128); state = 1; end_of_input = false; this.reader = reader; fsm_context = new FsmContext(); fsm_context.L = this; } private static int HexValue(int digit) { switch (digit) { case 65: case 97: return 10; case 66: case 98: return 11; case 67: case 99: return 12; case 68: case 100: return 13; case 69: case 101: return 14; case 70: case 102: return 15; default: return digit - 48; } } private static void PopulateFsmTables(out StateHandler[] fsm_handler_table, out int[] fsm_return_table) { fsm_handler_table = new StateHandler[28] { State1, State2, State3, State4, State5, State6, State7, State8, State9, State10, State11, State12, State13, State14, State15, State16, State17, State18, State19, State20, State21, State22, State23, State24, State25, State26, State27, State28 }; fsm_return_table = new int[28] { 65542, 0, 65537, 65537, 0, 65537, 0, 65537, 0, 0, 65538, 0, 0, 0, 65539, 0, 0, 65540, 65541, 65542, 0, 0, 65541, 65542, 0, 0, 0, 0 }; } private static char ProcessEscChar(int esc_char) { switch (esc_char) { case 34: case 39: case 47: case 92: return Convert.ToChar(esc_char); case 110: return '\n'; case 116: return '\t'; case 114: return '\r'; case 98: return '\b'; case 102: return '\f'; default: return '?'; } } private static bool State1(FsmContext ctx) { while (ctx.L.GetChar()) { if (ctx.L.input_char == 32 || (ctx.L.input_char >= 9 && ctx.L.input_char <= 13)) { continue; } if (ctx.L.input_char >= 49 && ctx.L.input_char <= 57) { ctx.L.string_buffer.Append((char)ctx.L.input_char); ctx.NextState = 3; return true; } switch (ctx.L.input_char) { case 34: ctx.NextState = 19; ctx.Return = true; return true; case 44: case 58: case 91: case 93: case 123: case 125: ctx.NextState = 1; ctx.Return = true; return true; case 45: ctx.L.string_buffer.Append((char)ctx.L.input_char); ctx.NextState = 2; return true; case 48: ctx.L.string_buffer.Append((char)ctx.L.input_char); ctx.NextState = 4; return true; case 102: ctx.NextState = 12; return true; case 110: ctx.NextState = 16; return true; case 116: ctx.NextState = 9; return true; case 39: if (!ctx.L.allow_single_quoted_strings) { return false; } ctx.L.input_char = 34; ctx.NextState = 23; ctx.Return = true; return true; case 47: if (!ctx.L.allow_comments) { return false; } ctx.NextState = 25; return true; default: return false; } } return true; } private static bool State2(FsmContext ctx) { ctx.L.GetChar(); if (ctx.L.input_char >= 49 && ctx.L.input_char <= 57) { ctx.L.string_buffer.Append((char)ctx.L.input_char); ctx.NextState = 3; return true; } if (ctx.L.input_char == 48) { ctx.L.string_buffer.Append((char)ctx.L.input_char); ctx.NextState = 4; return true; } return false; } private static bool State3(FsmContext ctx) { while (ctx.L.GetChar()) { if (ctx.L.input_char >= 48 && ctx.L.input_char <= 57) { ctx.L.string_buffer.Append((char)ctx.L.input_char); continue; } if (ctx.L.input_char == 32 || (ctx.L.input_char >= 9 && ctx.L.input_char <= 13)) { ctx.Return = true; ctx.NextState = 1; return true; } switch (ctx.L.input_char) { case 44: case 93: case 125: ctx.L.UngetChar(); ctx.Return = true; ctx.NextState = 1; return true; case 46: ctx.L.string_buffer.Append((char)ctx.L.input_char); ctx.NextState = 5; return true; case 69: case 101: ctx.L.string_buffer.Append((char)ctx.L.input_char); ctx.NextState = 7; return true; default: return false; } } return true; } private static bool State4(FsmContext ctx) { ctx.L.GetChar(); if (ctx.L.input_char == 32 || (ctx.L.input_char >= 9 && ctx.L.input_char <= 13)) { ctx.Return = true; ctx.NextState = 1; return true; } switch (ctx.L.input_char) { case 44: case 93: case 125: ctx.L.UngetChar(); ctx.Return = true; ctx.NextState = 1; return true; case 46: ctx.L.string_buffer.Append((char)ctx.L.input_char); ctx.NextState = 5; return true; case 69: case 101: ctx.L.string_buffer.Append((char)ctx.L.input_char); ctx.NextState = 7; return true; default: return false; } } private static bool State5(FsmContext ctx) { ctx.L.GetChar(); if (ctx.L.input_char >= 48 && ctx.L.input_char <= 57) { ctx.L.string_buffer.Append((char)ctx.L.input_char); ctx.NextState = 6; return true; } return false; } private static bool State6(FsmContext ctx) { while (ctx.L.GetChar()) { if (ctx.L.input_char >= 48 && ctx.L.input_char <= 57) { ctx.L.string_buffer.Append((char)ctx.L.input_char); continue; } if (ctx.L.input_char == 32 || (ctx.L.input_char >= 9 && ctx.L.input_char <= 13)) { ctx.Return = true; ctx.NextState = 1; return true; } switch (ctx.L.input_char) { case 44: case 93: case 125: ctx.L.UngetChar(); ctx.Return = true; ctx.NextState = 1; return true; case 69: case 101: ctx.L.string_buffer.Append((char)ctx.L.input_char); ctx.NextState = 7; return true; default: return false; } } return true; } private static bool State7(FsmContext ctx) { ctx.L.GetChar(); if (ctx.L.input_char >= 48 && ctx.L.input_char <= 57) { ctx.L.string_buffer.Append((char)ctx.L.input_char); ctx.NextState = 8; return true; } int num = ctx.L.input_char; if (num == 43 || num == 45) { ctx.L.string_buffer.Append((char)ctx.L.input_char); ctx.NextState = 8; return true; } return false; } private static bool State8(FsmContext ctx) { while (ctx.L.GetChar()) { if (ctx.L.input_char >= 48 && ctx.L.input_char <= 57) { ctx.L.string_buffer.Append((char)ctx.L.input_char); continue; } if (ctx.L.input_char == 32 || (ctx.L.input_char >= 9 && ctx.L.input_char <= 13)) { ctx.Return = true; ctx.NextState = 1; return true; } int num = ctx.L.input_char; if (num == 44 || num == 93 || num == 125) { ctx.L.UngetChar(); ctx.Return = true; ctx.NextState = 1; return true; } return false; } return true; } private static bool State9(FsmContext ctx) { ctx.L.GetChar(); if (ctx.L.input_char == 114) { ctx.NextState = 10; return true; } return false; } private static bool State10(FsmContext ctx) { ctx.L.GetChar(); if (ctx.L.input_char == 117) { ctx.NextState = 11; return true; } return false; } private static bool State11(FsmContext ctx) { ctx.L.GetChar(); if (ctx.L.input_char == 101) { ctx.Return = true; ctx.NextState = 1; return true; } return false; } private static bool State12(FsmContext ctx) { ctx.L.GetChar(); if (ctx.L.input_char == 97) { ctx.NextState = 13; return true; } return false; } private static bool State13(FsmContext ctx) { ctx.L.GetChar(); if (ctx.L.input_char == 108) { ctx.NextState = 14; return true; } return false; } private static bool State14(FsmContext ctx) { ctx.L.GetChar(); if (ctx.L.input_char == 115) { ctx.NextState = 15; return true; } return false; } private static bool State15(FsmContext ctx) { ctx.L.GetChar(); if (ctx.L.input_char == 101) { ctx.Return = true; ctx.NextState = 1; return true; } return false; } private static bool State16(FsmContext ctx) { ctx.L.GetChar(); if (ctx.L.input_char == 117) { ctx.NextState = 17; return true; } return false; } private static bool State17(FsmContext ctx) { ctx.L.GetChar(); if (ctx.L.input_char == 108) { ctx.NextState = 18; return true; } return false; } private static bool State18(FsmContext ctx) { ctx.L.GetChar(); if (ctx.L.input_char == 108) { ctx.Return = true; ctx.NextState = 1; return true; } return false; } private static bool State19(FsmContext ctx) { while (ctx.L.GetChar()) { switch (ctx.L.input_char) { case 34: ctx.L.UngetChar(); ctx.Return = true; ctx.NextState = 20; return true; case 92: ctx.StateStack = 19; ctx.NextState = 21; return true; } ctx.L.string_buffer.Append((char)ctx.L.input_char); } return true; } private static bool State20(FsmContext ctx) { ctx.L.GetChar(); if (ctx.L.input_char == 34) { ctx.Return = true; ctx.NextState = 1; return true; } return false; } private static bool State21(FsmContext ctx) { ctx.L.GetChar(); switch (ctx.L.input_char) { case 117: ctx.NextState = 22; return true; case 34: case 39: case 47: case 92: case 98: case 102: case 110: case 114: case 116: ctx.L.string_buffer.Append(ProcessEscChar(ctx.L.input_char)); ctx.NextState = ctx.StateStack; return true; default: return false; } } private static bool State22(FsmContext ctx) { int num = 0; int num2 = 4096; ctx.L.unichar = 0; while (ctx.L.GetChar()) { if ((ctx.L.input_char >= 48 && ctx.L.input_char <= 57) || (ctx.L.input_char >= 65 && ctx.L.input_char <= 70) || (ctx.L.input_char >= 97 && ctx.L.input_char <= 102)) { ctx.L.unichar += HexValue(ctx.L.input_char) * num2; num++; num2 /= 16; if (num == 4) { ctx.L.string_buffer.Append(Convert.ToChar(ctx.L.unichar)); ctx.NextState = ctx.StateStack; return true; } continue; } return false; } return true; } private static bool State23(FsmContext ctx) { while (ctx.L.GetChar()) { switch (ctx.L.input_char) { case 39: ctx.L.UngetChar(); ctx.Return = true; ctx.NextState = 24; return true; case 92: ctx.StateStack = 23; ctx.NextState = 21; return true; } ctx.L.string_buffer.Append((char)ctx.L.input_char); } return true; } private static bool State24(FsmContext ctx) { ctx.L.GetChar(); if (ctx.L.input_char == 39) { ctx.L.input_char = 34; ctx.Return = true; ctx.NextState = 1; return true; } return false; } private static bool State25(FsmContext ctx) { ctx.L.GetChar(); switch (ctx.L.input_char) { case 42: ctx.NextState = 27; return true; case 47: ctx.NextState = 26; return true; default: return false; } } private static bool State26(FsmContext ctx) { while (ctx.L.GetChar()) { if (ctx.L.input_char == 10) { ctx.NextState = 1; return true; } } return true; } private static bool State27(FsmContext ctx) { while (ctx.L.GetChar()) { if (ctx.L.input_char == 42) { ctx.NextState = 28; return true; } } return true; } private static bool State28(FsmContext ctx) { while (ctx.L.GetChar()) { if (ctx.L.input_char != 42) { if (ctx.L.input_char == 47) { ctx.NextState = 1; return true; } ctx.NextState = 27; return true; } } return true; } private bool GetChar() { if ((input_char = NextChar()) != -1) { return true; } end_of_input = true; return false; } private int NextChar() { if (input_buffer != 0) { int result = input_buffer; input_buffer = 0; return result; } return reader.Read(); } public bool NextToken() { fsm_context.Return = false; while (true) { if (!fsm_handler_table[state - 1](fsm_context)) { throw new JsonException(input_char); } if (end_of_input) { return false; } if (fsm_context.Return) { break; } state = fsm_context.NextState; } string_value = string_buffer.ToString(); string_buffer.Remove(0, string_buffer.Length); token = fsm_return_table[state - 1]; if (token == 65542) { token = input_char; } state = fsm_context.NextState; return true; } private void UngetChar() { input_buffer = input_char; } } internal enum ParserToken { None = 65536, Number, True, False, Null, CharSeq, Char, Text, Object, ObjectPrime, Pair, PairRest, Array, ArrayPrime, Value, ValueRest, String, End, Epsilon } } namespace NDesk.Options { internal class OptionValueCollection : IList, ICollection, IEnumerable, IList, ICollection, IEnumerable { private List values = new List(); private OptionContext c; bool ICollection.IsSynchronized => ((ICollection)values).IsSynchronized; object ICollection.SyncRoot => ((ICollection)values).SyncRoot; bool IList.IsFixedSize => false; object IList.this[int index] { get { return this[index]; } set { ((IList)values)[index] = value; } } public int Count => values.Count; public bool IsReadOnly => false; public string this[int index] { get { AssertValid(index); return (index < values.Count) ? values[index] : null; } set { values[index] = value; } } internal OptionValueCollection(OptionContext c) { this.c = c; } void ICollection.CopyTo(Array array, int index) { ((ICollection)values).CopyTo(array, index); } IEnumerator IEnumerable.GetEnumerator() { return values.GetEnumerator(); } int IList.Add(object value) { return ((IList)values).Add(value); } bool IList.Contains(object value) { return ((IList)values).Contains(value); } int IList.IndexOf(object value) { return ((IList)values).IndexOf(value); } void IList.Insert(int index, object value) { ((IList)values).Insert(index, value); } void IList.Remove(object value) { ((IList)values).Remove(value); } void IList.RemoveAt(int index) { ((IList)values).RemoveAt(index); } public void Add(string item) { values.Add(item); } public void Clear() { values.Clear(); } public bool Contains(string item) { return values.Contains(item); } public void CopyTo(string[] array, int arrayIndex) { values.CopyTo(array, arrayIndex); } public bool Remove(string item) { return values.Remove(item); } public IEnumerator GetEnumerator() { return values.GetEnumerator(); } public int IndexOf(string item) { return values.IndexOf(item); } public void Insert(int index, string item) { values.Insert(index, item); } public void RemoveAt(int index) { values.RemoveAt(index); } private void AssertValid(int index) { if (c.Option == null) { throw new InvalidOperationException("OptionContext.Option is null."); } if (index >= c.Option.MaxValueCount) { throw new ArgumentOutOfRangeException("index"); } if (c.Option.OptionValueType == OptionValueType.Required && index >= values.Count) { throw new OptionException(string.Format(c.OptionSet.MessageLocalizer("Missing required value for option '{0}'."), c.OptionName), c.OptionName); } } public List ToList() { return new List(values); } public string[] ToArray() { return values.ToArray(); } public override string ToString() { return string.Join(", ", values.ToArray()); } } internal class OptionContext { private Option option; private string name; private int index; private OptionSet set; private OptionValueCollection c; public Option Option { get { return option; } set { option = value; } } public string OptionName { get { return name; } set { name = value; } } public int OptionIndex { get { return index; } set { index = value; } } public OptionSet OptionSet => set; public OptionValueCollection OptionValues => c; public OptionContext(OptionSet set) { this.set = set; c = new OptionValueCollection(this); } } internal enum OptionValueType { None, Optional, Required } internal abstract class Option { private string prototype; private string description; private string[] names; private OptionValueType type; private int count; private string[] separators; private static readonly char[] NameTerminator = new char[2] { '=', ':' }; public string Prototype => prototype; public string Description => description; public OptionValueType OptionValueType => type; public int MaxValueCount => count; internal string[] Names => names; internal string[] ValueSeparators => separators; protected Option(string prototype, string description) : this(prototype, description, 1) { } protected Option(string prototype, string description, int maxValueCount) { if (prototype == null) { throw new ArgumentNullException("prototype"); } if (prototype.Length == 0) { throw new ArgumentException("Cannot be the empty string.", "prototype"); } if (maxValueCount < 0) { throw new ArgumentOutOfRangeException("maxValueCount"); } this.prototype = prototype; names = prototype.Split(new char[1] { '|' }); this.description = description; count = maxValueCount; type = ParsePrototype(); if (count == 0 && type != 0) { throw new ArgumentException("Cannot provide maxValueCount of 0 for OptionValueType.Required or OptionValueType.Optional.", "maxValueCount"); } if (type == OptionValueType.None && maxValueCount > 1) { throw new ArgumentException($"Cannot provide maxValueCount of {maxValueCount} for OptionValueType.None.", "maxValueCount"); } if (Array.IndexOf(names, "<>") >= 0 && ((names.Length == 1 && type != 0) || (names.Length > 1 && MaxValueCount > 1))) { throw new ArgumentException("The default option handler '<>' cannot require values.", "prototype"); } } protected static T Parse(string value, OptionContext c) { TypeConverter converter = TypeDescriptor.GetConverter(typeof(T)); T result = default(T); try { if (value != null) { result = (T)converter.ConvertFromString(value); } } catch (Exception innerException) { throw new OptionException(string.Format(c.OptionSet.MessageLocalizer("Could not convert string `{0}' to type {1} for option `{2}'."), value, typeof(T).Name, c.OptionName), c.OptionName, innerException); } return result; } public string[] GetNames() { return (string[])names.Clone(); } public string[] GetValueSeparators() { if (separators == null) { return new string[0]; } return (string[])separators.Clone(); } private OptionValueType ParsePrototype() { char c = '\0'; List list = new List(); for (int i = 0; i < names.Length; i++) { string text = names[i]; if (text.Length == 0) { throw new ArgumentException("Empty option names are not supported.", "prototype"); } int num = text.IndexOfAny(NameTerminator); if (num != -1) { names[i] = text.Substring(0, num); if (c != 0 && c != text[num]) { throw new ArgumentException($"Conflicting option types: '{c}' vs. '{text[num]}'.", "prototype"); } c = text[num]; AddSeparators(text, num, list); } } if (c == '\0') { return OptionValueType.None; } if (count <= 1 && list.Count != 0) { throw new ArgumentException($"Cannot provide key/value separators for Options taking {count} value(s).", "prototype"); } if (count > 1) { if (list.Count == 0) { separators = new string[2] { ":", "=" }; } else if (list.Count == 1 && list[0].Length == 0) { separators = null; } else { separators = list.ToArray(); } } return (c != '=') ? OptionValueType.Optional : OptionValueType.Required; } private static void AddSeparators(string name, int end, ICollection seps) { int num = -1; for (int i = end + 1; i < name.Length; i++) { switch (name[i]) { case '{': if (num != -1) { throw new ArgumentException($"Ill-formed name/value separator found in \"{name}\".", "prototype"); } num = i + 1; break; case '}': if (num == -1) { throw new ArgumentException($"Ill-formed name/value separator found in \"{name}\".", "prototype"); } seps.Add(name.Substring(num, i - num)); num = -1; break; default: if (num == -1) { seps.Add(name[i].ToString()); } break; } } if (num != -1) { throw new ArgumentException($"Ill-formed name/value separator found in \"{name}\".", "prototype"); } } public void Invoke(OptionContext c) { OnParseComplete(c); c.OptionName = null; c.Option = null; c.OptionValues.Clear(); } protected abstract void OnParseComplete(OptionContext c); public override string ToString() { return Prototype; } } [Serializable] internal class OptionException : Exception { private string option; public string OptionName => option; public OptionException() { } public OptionException(string message, string optionName) : base(message) { option = optionName; } public OptionException(string message, string optionName, Exception innerException) : base(message, innerException) { option = optionName; } protected OptionException(SerializationInfo info, StreamingContext context) : base(info, context) { option = info.GetString("OptionName"); } [@SecurityPermission(SecurityAction.LinkDemand, Flags = "SerializationFormatter")] public override void GetObjectData(SerializationInfo info, StreamingContext context) { base.GetObjectData(info, context); info.AddValue("OptionName", option); } } internal class OptionSet : KeyedCollection { private sealed class ActionOption : Option { private Action action; public ActionOption(string prototype, string description, int count, Action action) : base(prototype, description, count) { if (action == null) { throw new ArgumentNullException("action"); } this.action = action; } protected override void OnParseComplete(OptionContext c) { action(c.OptionValues); } } private sealed class ActionOption : Option { private Action action; public ActionOption(string prototype, string description, Action action) : base(prototype, description, 1) { if (action == null) { throw new ArgumentNullException("action"); } this.action = action; } protected override void OnParseComplete(OptionContext c) { action(Option.Parse(c.OptionValues[0], c)); } } private sealed class ActionOption : Option { private OptionAction action; public ActionOption(string prototype, string description, OptionAction action) : base(prototype, description, 2) { if (action == null) { throw new ArgumentNullException("action"); } this.action = action; } protected override void OnParseComplete(OptionContext c) { action(Option.Parse(c.OptionValues[0], c), Option.Parse(c.OptionValues[1], c)); } } [CompilerGenerated] private class <>c__CompilerGenerated0 { internal Action <1:action>; internal OptionSet <1:<>THIS>; public <>c__CompilerGenerated0(OptionSet parent) { <1:<>THIS> = parent; } } [CompilerGenerated] private class <>c__CompilerGenerated1 { internal OptionAction <2:action>; internal OptionSet <2:<>THIS>; public <>c__CompilerGenerated1(OptionSet parent) { <2:<>THIS> = parent; } } [CompilerGenerated] private class <>c__CompilerGenerated2 { } private const int OptionWidth = 29; private Converter localizer; private readonly Regex ValueOption; public Converter MessageLocalizer => localizer; public OptionSet() { _ = 1; this..ctor(new <>c__CompilerGenerated2().c__3); } public OptionSet(Converter localizer) { ValueOption = new Regex("^(?--|-|/)(?[^:=]+)((?[:=])(?.*))?$"); base..ctor(); this.localizer = localizer; } public OptionSet Add(string prototype, Action action) { return Add(prototype, null, action); } public OptionSet Add(string prototype, string description, Action action) { return Add(new ActionOption(prototype, description, action)); } public OptionSet Add(string prototype, OptionAction action) { return Add(prototype, null, action); } public OptionSet Add(string prototype, string description, OptionAction action) { return Add(new ActionOption(prototype, description, action)); } protected override string GetKeyForItem(Option item) { if (item == null) { throw new ArgumentNullException("option"); } if (item.Names != null && item.Names.Length > 0) { return item.Names[0]; } throw new InvalidOperationException("Option has no names!"); } [Obsolete("Use KeyedCollection.this[string]")] protected Option GetOptionForName(string option) { if (option == null) { throw new ArgumentNullException("option"); } try { return base[option]; } catch (KeyNotFoundException) { return null; } } protected override void InsertItem(int index, Option item) { base.InsertItem(index, item); AddImpl(item); } protected override void RemoveItem(int index) { base.RemoveItem(index); Option option = base.Items[index]; for (int i = 1; i < option.Names.Length; i++) { base.Dictionary.Remove(option.Names[i]); } } protected override void SetItem(int index, Option item) { base.SetItem(index, item); RemoveItem(index); AddImpl(item); } private void AddImpl(Option option) { if (option == null) { throw new ArgumentNullException("option"); } List list = new List(option.Names.Length); try { for (int i = 1; i < option.Names.Length; i++) { base.Dictionary.Add(option.Names[i], option); list.Add(option.Names[i]); } } catch (Exception) { List.Enumerator enumerator = list.GetEnumerator(); try { while (enumerator.MoveNext()) { string current = enumerator.Current; base.Dictionary.Remove(current); } } finally { enumerator.Dispose(); } throw; } } public new OptionSet Add(Option option) { base.Add(option); return this; } public OptionSet Add(string prototype, Action action) { return Add(prototype, null, action); } public OptionSet Add(string prototype, string description, Action action) { _ = 2; <>c__CompilerGenerated0 <>c__CompilerGenerated = new <>c__CompilerGenerated0(this); <>c__CompilerGenerated.<1:action> = action; if (<>c__CompilerGenerated.<1:action> == null) { throw new ArgumentNullException("action"); } Option item = new ActionOption(prototype, description, 1, <>c__CompilerGenerated.c__4); ((Collection