Decompiled source of RavenMap v1.9.15

RavenMap.dll

Decompiled a month ago
using System;
using System.Collections;
using System.Collections.Generic;
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.Versioning;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using TMPro;
using Unity.Collections;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.Rendering;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: InternalsVisibleTo("RavenMap.Tests")]
[assembly: AssemblyCompany("RavenMap")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.9.15.0")]
[assembly: AssemblyInformationalVersion("1.9.15")]
[assembly: AssemblyProduct("RavenMap")]
[assembly: AssemblyTitle("RavenMap")]
[assembly: AssemblyVersion("1.9.15.0")]
namespace DragonMotion.RavenMap;

internal static class RavenCommands
{
	private const string CommandName = "ravenmap";

	private static readonly FieldInfo TerminalCommandsField = AccessTools.Field(typeof(Terminal), "commands");

	private static ConsoleCommand _command;

	private static bool _active;

	internal static void Initialize()
	{
		//IL_001f: 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: Expected O, but got Unknown
		//IL_003d: Expected O, but got Unknown
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: Expected O, but got Unknown
		if (_command != null)
		{
			_active = true;
			return;
		}
		_command = new ConsoleCommand("ravenmap", string.Empty, new ConsoleEvent(Run), false, true, true, false, false, new ConsoleOptionsFetcher(GetOptions), false, true, true);
		_active = true;
		RefreshLocalization();
	}

	internal static void RefreshLocalization(string language = null)
	{
		if (_command != null)
		{
			_command.Description = (IsRussian(language) ? "Сброс общих автоматических отметок RavenMap" : "Reset RavenMap shared automatic pins");
		}
	}

	internal static void Shutdown()
	{
		_active = false;
		if (_command != null)
		{
			if (TerminalCommandsField?.GetValue(null) is Dictionary<string, ConsoleCommand> dictionary && dictionary.TryGetValue("ravenmap", out var value) && value == _command)
			{
				dictionary.Remove("ravenmap");
			}
			_command = null;
		}
	}

	private static void Run(ConsoleEventArgs args)
	{
		if (!_active)
		{
			return;
		}
		bool flag = IsRussian();
		if (args == null || args.Length != 3 || !string.Equals(args[1], "resetpins", StringComparison.OrdinalIgnoreCase) || !string.Equals(args[2], "confirm", StringComparison.OrdinalIgnoreCase))
		{
			if (args != null)
			{
				Terminal context = args.Context;
				if (context != null)
				{
					context.AddString(flag ? "Использование: ravenmap resetpins confirm" : "Usage: ravenmap resetpins confirm");
				}
			}
		}
		else if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer())
		{
			Terminal context2 = args.Context;
			if (context2 != null)
			{
				context2.AddString(flag ? "Сбрасывать общие автоматические отметки может только хост или администратор сервера." : "Only the host or a server administrator can reset shared automatic pins.");
			}
		}
		else
		{
			bool flag2 = RavenRuntime.RequestAutomaticPinReset();
			Terminal context3 = args.Context;
			if (context3 != null)
			{
				context3.AddString((!flag2) ? (flag ? "Не удалось сбросить автоматические отметки: мир или сетевой сеанс RavenMap ещё не готов." : "Automatic pins could not be reset because the RavenMap world/network session is not ready.") : (flag ? "Общие автоматические отметки сброшены. Загруженные подходящие объекты будут обнаружены повторно." : "Shared automatic pins were reset. Loaded eligible objects will be discovered again."));
			}
		}
	}

	private static List<string> GetOptions()
	{
		return new List<string> { "resetpins" };
	}

	private static bool IsRussian(string language = null)
	{
		try
		{
			object obj = language;
			if (obj == null)
			{
				Localization instance = Localization.instance;
				obj = ((instance != null) ? instance.GetSelectedLanguage() : null);
			}
			return ConfigText.IsRussian((string)obj);
		}
		catch
		{
			return false;
		}
	}
}
internal static class GameAccess
{
	private static FieldRef<Minimap, bool[]> _explored;

	private static FieldRef<Minimap, bool[]> _exploredOthers;

	private static FieldRef<Minimap, Texture2D> _fogTexture;

	private static FieldRef<Minimap, List<PinData>> _pins;

	private static FieldRef<Minimap, bool> _pinUpdateRequired;

	private static FieldRef<Minimap, Dictionary<Vector3, PinData>> _locationPins;

	private static FieldRef<Minimap, float> _updateLocationsTimer;

	private static FieldRef<MineRock, Collider[]> _mineRockHitAreas;

	private static FieldRef<MineRock5, MeshRenderer> _mineRock5MeshRenderer;

	private static Func<MineRock5, object> _mineRock5HitAreas;

	private static Func<object, float> _mineRock5HitAreaHealth;

	private static bool _initialized;

	internal static bool TryInitialize(out string error)
	{
		if (_initialized)
		{
			error = string.Empty;
			return true;
		}
		try
		{
			_explored = AccessTools.FieldRefAccess<Minimap, bool[]>("m_explored");
			_exploredOthers = AccessTools.FieldRefAccess<Minimap, bool[]>("m_exploredOthers");
			_fogTexture = AccessTools.FieldRefAccess<Minimap, Texture2D>("m_fogTexture");
			_pins = AccessTools.FieldRefAccess<Minimap, List<PinData>>("m_pins");
			_pinUpdateRequired = AccessTools.FieldRefAccess<Minimap, bool>("m_pinUpdateRequired");
			try
			{
				_locationPins = AccessTools.FieldRefAccess<Minimap, Dictionary<Vector3, PinData>>("m_locationPins");
				_updateLocationsTimer = AccessTools.FieldRefAccess<Minimap, float>("m_updateLocationsTimer");
			}
			catch
			{
				_locationPins = null;
				_updateLocationsTimer = null;
			}
			_mineRockHitAreas = AccessTools.FieldRefAccess<MineRock, Collider[]>("m_hitAreas");
			_mineRock5MeshRenderer = AccessTools.FieldRefAccess<MineRock5, MeshRenderer>("m_meshRenderer");
			FieldInfo fieldInfo = AccessTools.Field(typeof(MineRock5), "m_hitAreas");
			if (fieldInfo == null)
			{
				throw new MissingFieldException(typeof(MineRock5).FullName, "m_hitAreas");
			}
			_mineRock5HitAreas = BuildObjectFieldGetter<MineRock5>(fieldInfo);
			Type type = fieldInfo.FieldType.GetGenericArguments()[0];
			FieldInfo fieldInfo2 = AccessTools.Field(type, "m_health");
			if (fieldInfo2 == null || fieldInfo2.FieldType != typeof(float))
			{
				throw new MissingFieldException(type.FullName, "m_health");
			}
			_mineRock5HitAreaHealth = BuildFloatFieldGetter(fieldInfo2);
			if (_explored == null || _exploredOthers == null || _fogTexture == null || _pins == null || _pinUpdateRequired == null || _mineRockHitAreas == null || _mineRock5MeshRenderer == null || _mineRock5HitAreas == null || _mineRock5HitAreaHealth == null)
			{
				throw new MissingFieldException("One or more required Minimap accessors could not be created.");
			}
			_initialized = true;
			error = string.Empty;
			return true;
		}
		catch (Exception ex)
		{
			_explored = null;
			_exploredOthers = null;
			_fogTexture = null;
			_pins = null;
			_pinUpdateRequired = null;
			_locationPins = null;
			_updateLocationsTimer = null;
			_mineRockHitAreas = null;
			_mineRock5MeshRenderer = null;
			_mineRock5HitAreas = null;
			_mineRock5HitAreaHealth = null;
			_initialized = false;
			error = ex.GetType().Name + ": " + ex.Message;
			return false;
		}
	}

	internal static bool[] GetExplored(Minimap map)
	{
		if (!((Object)(object)map != (Object)null) || _explored == null)
		{
			return null;
		}
		return _explored.Invoke(map);
	}

	internal static bool[] GetExploredOthers(Minimap map)
	{
		if (!((Object)(object)map != (Object)null) || _exploredOthers == null)
		{
			return null;
		}
		return _exploredOthers.Invoke(map);
	}

	internal static bool TryIsWorldPositionExplored(Minimap map, Vector3 position, out bool explored)
	{
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		explored = false;
		if (map == null)
		{
			return false;
		}
		return TryIsWorldPositionExplored(GetExplored(map), GetExploredOthers(map), map.m_textureSize, map.m_pixelSize, position, out explored);
	}

	internal static bool TryIsWorldPositionExplored(bool[] local, bool[] shared, int size, float pixelSize, Vector3 position, out bool explored)
	{
		//IL_002c: 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)
		explored = false;
		if (size <= 0 || pixelSize <= 0f || local == null || shared == null || local.Length != size * size || shared.Length != size * size)
		{
			return false;
		}
		int num = size / 2;
		int num2 = Mathf.RoundToInt(position.x / pixelSize + (float)num);
		int num3 = Mathf.RoundToInt(position.z / pixelSize + (float)num);
		if ((uint)num2 >= (uint)size || (uint)num3 >= (uint)size)
		{
			return true;
		}
		int num4 = num3 * size + num2;
		explored = local[num4] || shared[num4];
		return true;
	}

	internal static Texture2D GetFogTexture(Minimap map)
	{
		if (!((Object)(object)map != (Object)null) || _fogTexture == null)
		{
			return null;
		}
		return _fogTexture.Invoke(map);
	}

	internal static List<PinData> GetPins(Minimap map)
	{
		if (!((Object)(object)map != (Object)null) || _pins == null)
		{
			return null;
		}
		return _pins.Invoke(map);
	}

	internal static Dictionary<Vector3, PinData> GetLocationPins(Minimap map)
	{
		if (!((Object)(object)map != (Object)null) || _locationPins == null)
		{
			return null;
		}
		return _locationPins.Invoke(map);
	}

	internal static void RequestLocationPinRefresh(Minimap map)
	{
		if (!((Object)(object)map == (Object)null) && _updateLocationsTimer != null)
		{
			_updateLocationsTimer.Invoke(map) = 0f;
		}
	}

	internal static void MarkPinsDirty(Minimap map)
	{
		if (!((Object)(object)map == (Object)null) && _pinUpdateRequired != null)
		{
			_pinUpdateRequired.Invoke(map) = true;
		}
	}

	internal static int GetMineRockHitAreaCount(MineRock rock)
	{
		if (rock == null || _mineRockHitAreas == null)
		{
			return 0;
		}
		Collider[] obj = _mineRockHitAreas.Invoke(rock);
		if (obj == null)
		{
			return 0;
		}
		return obj.Length;
	}

	internal static int GetMineRock5HitAreaCount(MineRock5 rock)
	{
		if (rock == null || _mineRock5HitAreas == null)
		{
			return 0;
		}
		if (!(_mineRock5HitAreas(rock) is ICollection collection))
		{
			return 0;
		}
		return collection.Count;
	}

	internal static bool TryMeasureMineRock5HitAreas(MineRock5 rock, float maximumHealth, out float remaining, out int totalParts, out int remainingParts)
	{
		remaining = 0f;
		totalParts = 0;
		remainingParts = 0;
		if (rock == null || maximumHealth <= 0f || _mineRock5HitAreas == null || _mineRock5HitAreaHealth == null || !(_mineRock5HitAreas(rock) is IList { Count: not 0 } list))
		{
			return false;
		}
		totalParts = list.Count;
		for (int i = 0; i < list.Count; i++)
		{
			object obj = list[i];
			if (obj != null)
			{
				float num = Mathf.Clamp(_mineRock5HitAreaHealth(obj), 0f, maximumHealth);
				remaining += num;
				if (num > 0f)
				{
					remainingParts++;
				}
			}
		}
		return true;
	}

	internal static MeshRenderer GetMineRock5CombinedRenderer(MineRock5 rock)
	{
		if (rock != null && _mineRock5MeshRenderer != null)
		{
			return _mineRock5MeshRenderer.Invoke(rock);
		}
		return null;
	}

	internal static bool TryGetMapState(Minimap map, out bool[] explored, out Texture2D fogTexture, out int textureSize)
	{
		explored = GetExplored(map);
		fogTexture = GetFogTexture(map);
		textureSize = (((Object)(object)map != (Object)null) ? map.m_textureSize : 0);
		if (explored != null && (Object)(object)fogTexture != (Object)null && textureSize > 0)
		{
			return explored.Length == textureSize * textureSize;
		}
		return false;
	}

	internal static bool ExploreRed(bool[] explored, Texture2D fogTexture, int size, int x, int y)
	{
		//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_004b: Unknown result type (might be due to invalid IL or missing references)
		if (explored == null || (Object)(object)fogTexture == (Object)null || size <= 0 || explored.Length != size * size || (uint)x >= (uint)size || (uint)y >= (uint)size)
		{
			return false;
		}
		int num = y * size + x;
		if (explored[num])
		{
			return false;
		}
		Color pixel = fogTexture.GetPixel(x, y);
		pixel.r = 0f;
		fogTexture.SetPixel(x, y, pixel);
		explored[num] = true;
		return true;
	}

	private static Func<T, object> BuildObjectFieldGetter<T>(FieldInfo field)
	{
		DynamicMethod dynamicMethod = new DynamicMethod("RavenMap_Get_" + typeof(T).Name + "_" + field.Name, typeof(object), new Type[1] { typeof(T) }, typeof(GameAccess), skipVisibility: true);
		ILGenerator iLGenerator = dynamicMethod.GetILGenerator();
		iLGenerator.Emit(OpCodes.Ldarg_0);
		iLGenerator.Emit(OpCodes.Ldfld, field);
		if (field.FieldType.IsValueType)
		{
			iLGenerator.Emit(OpCodes.Box, field.FieldType);
		}
		iLGenerator.Emit(OpCodes.Ret);
		return (Func<T, object>)dynamicMethod.CreateDelegate(typeof(Func<T, object>));
	}

	private static Func<object, float> BuildFloatFieldGetter(FieldInfo field)
	{
		DynamicMethod dynamicMethod = new DynamicMethod("RavenMap_Get_" + field.DeclaringType.Name + "_" + field.Name, typeof(float), new Type[1] { typeof(object) }, typeof(GameAccess), skipVisibility: true);
		ILGenerator iLGenerator = dynamicMethod.GetILGenerator();
		iLGenerator.Emit(OpCodes.Ldarg_0);
		iLGenerator.Emit(OpCodes.Castclass, field.DeclaringType);
		iLGenerator.Emit(OpCodes.Ldfld, field);
		iLGenerator.Emit(OpCodes.Ret);
		return (Func<object, float>)dynamicMethod.CreateDelegate(typeof(Func<object, float>));
	}
}
internal enum WorldLocationKind : byte
{
	None,
	Trader,
	Port
}
internal sealed class MoreWorldLocationsSupport
{
	internal const string PluginGuid = "warpalicious.More_World_Locations_AIO";

	internal const string TraderGroup = "MWL_Trader";

	internal const string PortGroup = "MWL_Ports";

	private readonly Dictionary<string, WorldLocationKind> _locations = new Dictionary<string, WorldLocationKind>(StringComparer.Ordinal);

	internal bool HasTraders { get; private set; }

	internal bool HasPorts { get; private set; }

	internal bool HasAny
	{
		get
		{
			if (!HasTraders)
			{
				return HasPorts;
			}
			return true;
		}
	}

	internal IReadOnlyDictionary<string, WorldLocationKind> Locations => _locations;

	internal bool Refresh(ZoneSystem zoneSystem)
	{
		Dictionary<string, WorldLocationKind> dictionary = new Dictionary<string, WorldLocationKind>(StringComparer.Ordinal);
		bool flag = Chainloader.PluginInfos.ContainsKey("warpalicious.More_World_Locations_AIO");
		if (flag && zoneSystem?.m_locations != null)
		{
			for (int i = 0; i < zoneSystem.m_locations.Count; i++)
			{
				ZoneLocation val = zoneSystem.m_locations[i];
				if (val != null && val.m_enable && (string.Equals(val.m_group, "MWL_Trader", StringComparison.Ordinal) || string.Equals(val.m_group, "MWL_Ports", StringComparison.Ordinal)))
				{
					string text = ResolveRegisteredPrefabName(val);
					WorldLocationKind worldLocationKind = ClassifyRegisteredLocation(text, val.m_group, val.m_enable, flag);
					if (worldLocationKind != WorldLocationKind.None)
					{
						dictionary[text] = worldLocationKind;
					}
				}
			}
		}
		bool flag2 = !CatalogsEqual(_locations, dictionary);
		if (flag2)
		{
			_locations.Clear();
			foreach (KeyValuePair<string, WorldLocationKind> item in dictionary)
			{
				_locations.Add(item.Key, item.Value);
			}
		}
		HasTraders = ContainsKind(_locations, WorldLocationKind.Trader);
		HasPorts = ContainsKind(_locations, WorldLocationKind.Port);
		return flag2;
	}

	internal static string ResolveRegisteredPrefabName(ZoneLocation location)
	{
		if (location == null)
		{
			return string.Empty;
		}
		string text = location.m_prefabName;
		if (string.IsNullOrWhiteSpace(text))
		{
			text = location.m_name;
		}
		if (!string.IsNullOrWhiteSpace(text))
		{
			return text.Trim();
		}
		return string.Empty;
	}

	internal bool TryClassify(string prefab, out WorldLocationKind kind)
	{
		kind = WorldLocationKind.None;
		if (!string.IsNullOrWhiteSpace(prefab))
		{
			return _locations.TryGetValue(prefab, out kind);
		}
		return false;
	}

	internal void Clear()
	{
		_locations.Clear();
		HasTraders = false;
		HasPorts = false;
	}

	internal static WorldLocationKind ClassifyRegisteredLocation(string prefab, string group, bool enabled, bool pluginLoaded)
	{
		if (!pluginLoaded || !enabled || string.IsNullOrWhiteSpace(prefab) || !prefab.StartsWith("MWL_", StringComparison.Ordinal))
		{
			return WorldLocationKind.None;
		}
		if (string.Equals(group, "MWL_Trader", StringComparison.Ordinal))
		{
			return WorldLocationKind.Trader;
		}
		if (!string.Equals(group, "MWL_Ports", StringComparison.Ordinal))
		{
			return WorldLocationKind.None;
		}
		return WorldLocationKind.Port;
	}

	private static bool ContainsKind(Dictionary<string, WorldLocationKind> catalog, WorldLocationKind kind)
	{
		foreach (WorldLocationKind value in catalog.Values)
		{
			if (value == kind)
			{
				return true;
			}
		}
		return false;
	}

	private static bool CatalogsEqual(Dictionary<string, WorldLocationKind> left, Dictionary<string, WorldLocationKind> right)
	{
		if (left.Count != right.Count)
		{
			return false;
		}
		foreach (KeyValuePair<string, WorldLocationKind> item in left)
		{
			if (!right.TryGetValue(item.Key, out var value) || value != item.Value)
			{
				return false;
			}
		}
		return true;
	}
}
internal static class UpgradeWorldSupport
{
	internal const string PluginGuid = "upgrade_world";

	private const int RetainedZoneCapacityLimit = 4096;

	private static HashSet<Vector2i> _resetZones = new HashSet<Vector2i>();

	private static bool _pluginDetected;

	private static bool _installed;

	private static bool _locationRegistryChanged;

	private static int _generationScopeDepth;

	private static bool _operationActive;

	private static bool _missingLoadingZoneLogged;

	private static FieldRef<ZoneSystem, Dictionary<Vector2i, List<ZDO>>> _loadingObjectsInZones;

	private static Harmony _generationHarmony;

	private static Harmony _mutationHarmony;

	private static Harmony _asyncDungeonSafetyHarmony;

	internal static bool IsDetected => _pluginDetected;

	internal static bool SuppressAutomaticDiscovery
	{
		get
		{
			if (_installed)
			{
				if (_generationScopeDepth <= 0)
				{
					return _operationActive;
				}
				return true;
			}
			return false;
		}
	}

	internal static bool HideUnexploredLocationPins => _pluginDetected;

	internal static bool HideUnexploredAutomaticPins => _pluginDetected;

	internal static bool ShouldRetireAutomaticSource(PinRecord record, ISet<Vector2i> resetZones, bool locationRegistryChanged, Func<string, bool> locationSourceExists)
	{
		//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)
		if (record == null)
		{
			return false;
		}
		if (resetZones != null && resetZones.Contains(ZoneSystem.GetZone(record.Position)))
		{
			return true;
		}
		if (locationRegistryChanged && record.Category == PinCategory.Dungeon && locationSourceExists != null)
		{
			return !locationSourceExists(record.SourceId);
		}
		return false;
	}

	internal static void TryInstall()
	{
		//IL_0062: Unknown result type (might be due to invalid IL or missing references)
		//IL_006c: Expected O, but got Unknown
		//IL_0094: Unknown result type (might be due to invalid IL or missing references)
		//IL_009e: Expected O, but got Unknown
		//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d0: Expected O, but got Unknown
		Shutdown();
		if (!Chainloader.PluginInfos.TryGetValue("upgrade_world", out var value))
		{
			return;
		}
		_pluginDetected = true;
		Assembly assembly = ((value == null) ? null : ((object)value.Instance)?.GetType().Assembly);
		if (assembly == null)
		{
			ManualLogSource log = RavenMapPlugin.Log;
			if (log != null)
			{
				log.LogWarning((object)"Upgrade World was detected by GUID, but its loaded assembly was unavailable; RavenMap left the optional integration disabled.");
			}
			return;
		}
		int num = 0;
		_generationHarmony = new Harmony("dragonmotion.ravenmap.upgrade-world.generate");
		if (TryInstallGenerateGuard(_generationHarmony, assembly))
		{
			num++;
		}
		else
		{
			_generationHarmony.UnpatchSelf();
			_generationHarmony = null;
		}
		_mutationHarmony = new Harmony("dragonmotion.ravenmap.upgrade-world.mutation");
		if (TryInstallMutationReconciliation(_mutationHarmony, assembly))
		{
			num++;
		}
		else
		{
			_mutationHarmony.UnpatchSelf();
			_mutationHarmony = null;
		}
		_asyncDungeonSafetyHarmony = new Harmony("dragonmotion.ravenmap.upgrade-world.async-dungeon");
		if (TryInstallAsyncDungeonCleanupGuard(_asyncDungeonSafetyHarmony, assembly))
		{
			num++;
		}
		else
		{
			_asyncDungeonSafetyHarmony.UnpatchSelf();
			_asyncDungeonSafetyHarmony = null;
		}
		_installed = num > 0;
		if (_installed)
		{
			ManualLogSource log2 = RavenMapPlugin.Log;
			if (log2 != null)
			{
				log2.LogInfo((object)("Upgrade World compatibility enabled by GUID (no version lock): " + num + "/3 hook groups active."));
			}
		}
		else
		{
			ManualLogSource log3 = RavenMapPlugin.Log;
			if (log3 != null)
			{
				log3.LogWarning((object)"Upgrade World was detected by GUID, but its operation API was not recognized; RavenMap continued without Upgrade World operation hooks.");
			}
		}
	}

	internal static void Shutdown()
	{
		Harmony generationHarmony = _generationHarmony;
		if (generationHarmony != null)
		{
			generationHarmony.UnpatchSelf();
		}
		Harmony mutationHarmony = _mutationHarmony;
		if (mutationHarmony != null)
		{
			mutationHarmony.UnpatchSelf();
		}
		Harmony asyncDungeonSafetyHarmony = _asyncDungeonSafetyHarmony;
		if (asyncDungeonSafetyHarmony != null)
		{
			asyncDungeonSafetyHarmony.UnpatchSelf();
		}
		_generationHarmony = null;
		_mutationHarmony = null;
		_asyncDungeonSafetyHarmony = null;
		_pluginDetected = false;
		_installed = false;
		_locationRegistryChanged = false;
		_generationScopeDepth = 0;
		_operationActive = false;
		_missingLoadingZoneLogged = false;
		_loadingObjectsInZones = null;
		ReleaseResetZones();
	}

	private static bool TryInstallAsyncDungeonCleanupGuard(Harmony harmony, Assembly assembly)
	{
		//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e1: Expected O, but got Unknown
		//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
		//IL_0108: Expected O, but got Unknown
		//IL_0121: Unknown result type (might be due to invalid IL or missing references)
		//IL_012f: Expected O, but got Unknown
		Type type = assembly.GetType("UpgradeWorld.Executor", throwOnError: false);
		MethodInfo methodInfo = ((type == null) ? null : AccessTools.DeclaredMethod(type, "StartExecution", Type.EmptyTypes, (Type[])null));
		MethodInfo methodInfo2 = ((type == null) ? null : AccessTools.DeclaredMethod(type, "StopExecution", Type.EmptyTypes, (Type[])null));
		MethodInfo methodInfo3 = AccessTools.DeclaredMethod(typeof(ZoneSystem), "UnsetLoadingInZone", new Type[1] { typeof(ZDO) }, (Type[])null);
		if (methodInfo == null || methodInfo2 == null || methodInfo3 == null || AccessTools.Field(typeof(ZoneSystem), "m_loadingObjectsInZones") == null)
		{
			return false;
		}
		try
		{
			_loadingObjectsInZones = AccessTools.FieldRefAccess<ZoneSystem, Dictionary<Vector2i, List<ZDO>>>("m_loadingObjectsInZones");
			harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(UpgradeWorldSupport), "ExecutorStartPostfix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(UpgradeWorldSupport), "ExecutorStopSafetyFinalizer", (Type[])null, (Type[])null)), (HarmonyMethod)null);
			harmony.Patch((MethodBase)methodInfo3, new HarmonyMethod(AccessTools.Method(typeof(UpgradeWorldSupport), "UnsetLoadingInZonePrefix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			return true;
		}
		catch (Exception ex)
		{
			_loadingObjectsInZones = null;
			ManualLogSource log = RavenMapPlugin.Log;
			if (log != null)
			{
				log.LogWarning((object)("Could not install the Upgrade World asynchronous dungeon cleanup guard: " + ex.GetType().Name + ": " + ex.Message));
			}
			return false;
		}
	}

	private static void ExecutorStartPostfix()
	{
		_operationActive = true;
		_missingLoadingZoneLogged = false;
	}

	private static Exception ExecutorStopSafetyFinalizer(Exception __exception)
	{
		_operationActive = false;
		_missingLoadingZoneLogged = false;
		return __exception;
	}

	private static bool UnsetLoadingInZonePrefix(ZoneSystem __instance, ZDO zdo)
	{
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		if (!_operationActive || (Object)(object)__instance == (Object)null || zdo == null || _loadingObjectsInZones == null)
		{
			return true;
		}
		try
		{
			Dictionary<Vector2i, List<ZDO>> dictionary = _loadingObjectsInZones.Invoke(__instance);
			if (dictionary == null || !ShouldSkipMissingLoadingZone(operationActive: true, dictionary.ContainsKey(zdo.GetSector())))
			{
				return true;
			}
			if (!_missingLoadingZoneLogged)
			{
				_missingLoadingZoneLogged = true;
				ManualLogSource log = RavenMapPlugin.Log;
				if (log != null)
				{
					log.LogWarning((object)"Upgrade World removed a zone while an asynchronous dungeon was still releasing it; RavenMap skipped the redundant vanilla unregister call.");
				}
			}
			return false;
		}
		catch
		{
			return true;
		}
	}

	internal static bool ShouldSkipMissingLoadingZone(bool operationActive, bool zonePresent)
	{
		if (operationActive)
		{
			return !zonePresent;
		}
		return false;
	}

	private static bool TryInstallGenerateGuard(Harmony harmony, Assembly assembly)
	{
		//IL_0074: 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_009c: Expected O, but got Unknown
		//IL_009c: Expected O, but got Unknown
		Type type = assembly.GetType("UpgradeWorld.Generate", throwOnError: false);
		MethodInfo methodInfo = ((type == null) ? null : AccessTools.DeclaredMethod(type, "ExecuteZone", new Type[1] { typeof(Vector2i) }, (Type[])null));
		if (methodInfo == null || methodInfo.ReturnType != typeof(bool))
		{
			return false;
		}
		try
		{
			harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(AccessTools.Method(typeof(UpgradeWorldSupport), "GenerateExecuteZonePrefix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(UpgradeWorldSupport), "GenerateExecuteZoneFinalizer", (Type[])null, (Type[])null)), (HarmonyMethod)null);
			return true;
		}
		catch (Exception ex)
		{
			ManualLogSource log = RavenMapPlugin.Log;
			if (log != null)
			{
				log.LogWarning((object)("Could not install the Upgrade World generation guard: " + ex.GetType().Name + ": " + ex.Message));
			}
			return false;
		}
	}

	private static bool TryInstallMutationReconciliation(Harmony harmony, Assembly assembly)
	{
		//IL_0198: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a5: Expected O, but got Unknown
		Type type = assembly.GetType("UpgradeWorld.Executor", throwOnError: false);
		MethodInfo methodInfo = ((type == null) ? null : AccessTools.DeclaredMethod(type, "StopExecution", Type.EmptyTypes, (Type[])null));
		if (methodInfo == null)
		{
			return false;
		}
		List<Action> list = new List<Action>();
		Type type2 = assembly.GetType("UpgradeWorld.ResetZones", throwOnError: false);
		MethodInfo resetZone = ((type2 == null) ? null : AccessTools.DeclaredMethod(type2, "ExecuteZone", new Type[1] { typeof(Vector2i) }, (Type[])null));
		if (resetZone != null && resetZone.ReturnType == typeof(bool))
		{
			list.Add(delegate
			{
				//IL_0023: Unknown result type (might be due to invalid IL or missing references)
				//IL_0030: Expected O, but got Unknown
				harmony.Patch((MethodBase)resetZone, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(UpgradeWorldSupport), "ResetZonePostfix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			});
		}
		Type type3 = assembly.GetType("UpgradeWorld.RemoveLocations", throwOnError: false);
		AddCountedMutationPatch(harmony, type3, "RemoveSpawned", list);
		AddCountedMutationPatch(harmony, type3, "RemoveNotSpawned", list);
		Type type4 = assembly.GetType("UpgradeWorld.DistributeLocations", throwOnError: false);
		MethodInfo distributionEnd = ((type4 == null) ? null : AccessTools.DeclaredMethod(type4, "OnEnd", Type.EmptyTypes, (Type[])null));
		if (distributionEnd != null)
		{
			list.Add(delegate
			{
				//IL_0023: Unknown result type (might be due to invalid IL or missing references)
				//IL_0030: Expected O, but got Unknown
				harmony.Patch((MethodBase)distributionEnd, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(UpgradeWorldSupport), "LocationRegistryChangedPostfix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			});
		}
		if (list.Count == 0)
		{
			return false;
		}
		try
		{
			for (int num = 0; num < list.Count; num++)
			{
				list[num]();
			}
			harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(UpgradeWorldSupport), "ExecutorStopPostfix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			return true;
		}
		catch (Exception ex)
		{
			ManualLogSource log = RavenMapPlugin.Log;
			if (log != null)
			{
				log.LogWarning((object)("Could not install Upgrade World mutation reconciliation: " + ex.GetType().Name + ": " + ex.Message));
			}
			return false;
		}
	}

	private static void AddCountedMutationPatch(Harmony harmony, Type type, string methodName, ICollection<Action> patches)
	{
		MethodInfo method = ((type == null) ? null : AccessTools.DeclaredMethod(type, methodName, Type.EmptyTypes, (Type[])null));
		if (!(method == null) && !(method.ReturnType != typeof(int)))
		{
			patches.Add(delegate
			{
				//IL_0023: Unknown result type (might be due to invalid IL or missing references)
				//IL_0030: Expected O, but got Unknown
				harmony.Patch((MethodBase)method, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(UpgradeWorldSupport), "CountedLocationMutationPostfix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			});
		}
	}

	private static void GenerateExecuteZonePrefix(out bool __state)
	{
		__state = true;
		_generationScopeDepth++;
	}

	private static Exception GenerateExecuteZoneFinalizer(Exception __exception, bool __state)
	{
		if (__state && _generationScopeDepth > 0)
		{
			_generationScopeDepth--;
		}
		return __exception;
	}

	private static void ResetZonePostfix(Vector2i __0, bool __result)
	{
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		if (__result)
		{
			_resetZones.Add(__0);
		}
	}

	private static void CountedLocationMutationPostfix(int __result)
	{
		if (__result > 0)
		{
			_locationRegistryChanged = true;
		}
	}

	private static void LocationRegistryChangedPostfix()
	{
		_locationRegistryChanged = true;
	}

	private static void ExecutorStopPostfix()
	{
		try
		{
			FlushPendingMutation();
		}
		catch (Exception ex)
		{
			ManualLogSource log = RavenMapPlugin.Log;
			if (log != null)
			{
				log.LogWarning((object)("Upgrade World completed, but RavenMap could not reconcile its automatic pins: " + ex.GetType().Name + ": " + ex.Message));
			}
		}
		finally
		{
			_generationScopeDepth = 0;
			_locationRegistryChanged = false;
			ReleaseResetZones();
		}
	}

	private static void FlushPendingMutation()
	{
		if (_resetZones.Count != 0 || _locationRegistryChanged)
		{
			bool locationRegistryChanged = _locationRegistryChanged;
			RavenRuntime.OnUpgradeWorldMutationCompleted(_resetZones, locationRegistryChanged);
		}
	}

	private static void ReleaseResetZones()
	{
		if (_resetZones.Count > 4096)
		{
			_resetZones = new HashSet<Vector2i>();
		}
		else
		{
			_resetZones.Clear();
		}
	}
}
internal enum ValheimLocationKind : byte
{
	None,
	StartTemple,
	Haldor,
	Hildir,
	BogWitch,
	HildirMystery,
	HildirCave,
	HildirTower
}
internal static class ValheimLocationSupport
{
	internal static bool TryClassifyLocation(string prefab, out ValheimLocationKind kind)
	{
		switch (prefab)
		{
		case "StartTemple":
			kind = ValheimLocationKind.StartTemple;
			return true;
		case "Vendor_BlackForest":
			kind = ValheimLocationKind.Haldor;
			return true;
		case "Hildir_camp":
			kind = ValheimLocationKind.Hildir;
			return true;
		case "BogWitch_Camp":
			kind = ValheimLocationKind.BogWitch;
			return true;
		default:
			kind = ValheimLocationKind.None;
			return false;
		}
	}

	internal static bool TryClassifyPinType(PinType type, out ValheimLocationKind kind)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0003: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Expected I4, but got Unknown
		switch (type - 14)
		{
		case 0:
			kind = ValheimLocationKind.HildirMystery;
			return true;
		case 1:
			kind = ValheimLocationKind.HildirCave;
			return true;
		case 2:
			kind = ValheimLocationKind.HildirTower;
			return true;
		default:
			kind = ValheimLocationKind.None;
			return false;
		}
	}

	internal static string IconName(ValheimLocationKind kind)
	{
		return kind switch
		{
			ValheimLocationKind.StartTemple => "valheim-start", 
			ValheimLocationKind.Haldor => "valheim-haldor", 
			ValheimLocationKind.Hildir => "valheim-hildir", 
			ValheimLocationKind.BogWitch => "valheim-bogwitch", 
			ValheimLocationKind.HildirMystery => "valheim-hildir1", 
			ValheimLocationKind.HildirCave => "valheim-hildir2", 
			ValheimLocationKind.HildirTower => "valheim-hildir3", 
			_ => string.Empty, 
		};
	}

	internal static string FilterKey(ValheimLocationKind kind)
	{
		return kind switch
		{
			ValheimLocationKind.StartTemple => "valheim.start", 
			ValheimLocationKind.Haldor => "valheim.haldor", 
			ValheimLocationKind.Hildir => "valheim.hildir", 
			ValheimLocationKind.BogWitch => "valheim.bogwitch", 
			ValheimLocationKind.HildirMystery => "valheim.hildir1", 
			ValheimLocationKind.HildirCave => "valheim.hildir2", 
			ValheimLocationKind.HildirTower => "valheim.hildir3", 
			_ => string.Empty, 
		};
	}
}
internal static class ConfigText
{
	private static readonly Dictionary<string, string> Russian = new Dictionary<string, string>(StringComparer.Ordinal)
	{
		["Vanilla pin size"] = "Размер ванильных значков",
		["Other pin size"] = "Размер других отметок",
		["Dungeon pin size"] = "Размер значков подземелий",
		["Pickable pin size"] = "Размер значков собираемых ресурсов",
		["Resource pin size"] = "Размер значков ресурсов",
		["More World Locations pin size"] = "Размер значков More World Locations",
		["Local size multiplier for Valheim map marks, locations and Hildir pins."] = "Локальный множитель размера отметок карты, локаций и значков Хильдир из Valheim.",
		["Local size multiplier for portal, ship and cart pins."] = "Локальный множитель размера отметок порталов, кораблей и повозок.",
		["Local size multiplier for dungeon pins."] = "Локальный множитель размера отметок подземелий.",
		["Local size multiplier for pickable-resource pins."] = "Локальный множитель размера отметок собираемых ресурсов.",
		["Local size multiplier for deposit and vein pins."] = "Локальный множитель размера отметок залежей и жил.",
		["Local visual size for More World Locations trader and port pins; built-in double size is normalized."] = "Локальный размер значков торговцев и портов More World Locations; встроенное удвоение размера нормализуется.",
		["01 - Interface"] = "01 — Интерфейс",
		["02 - Sharing"] = "02 — Общая карта",
		["03 - Discovery"] = "03 — Обнаружение",
		["04 - Resources"] = "04 — Ресурсы",
		["04.1 - Pickables"] = "04.1 — Собираемые ресурсы",
		["05 - Dungeons"] = "05 — Подземелья",
		["06 - Markers"] = "06 — Метки",
		["07 - Deduplication"] = "07 — Дедупликация",
		["08 - Shimmer"] = "08 — Подсветка",
		["08.1 - Pulse"] = "08.1 — Пульсация",
		["08.2 - Sweep"] = "08.2 — Переливание",
		["08.3 - X-ray"] = "08.3 — Рентген",
		["09 - Performance"] = "09 — Производительность",
		["10 - Diagnostics"] = "10 — Диагностика",
		["Enabled"] = "Включено",
		["Automatic pin names"] = "Названия автометок",
		["Portal names"] = "Названия порталов",
		["Filter scroll speed"] = "Скорость прокрутки",
		["Shared fog"] = "Общий туман войны",
		["Shared automatic pins"] = "Общие автометки",
		["Resource radius"] = "Радиус ресурсов",
		["Dungeon radius"] = "Радиус подземелий",
		["Silver discovery"] = "Обнаружение серебра",
		["Underground resources"] = "Подземные ресурсы",
		["Discovery radius"] = "Радиус обнаружения",
		["Cross out after harvest"] = "Зачёркивать после сбора",
		["Merge distance"] = "Дистанция слияния",
		["Remove after depletion"] = "Удаление после выработки",
		["Progress update step"] = "Шаг обновления прогресса",
		["Progress update interval"] = "Интервал обновления прогресса",
		["Source prefab allow list"] = "Разрешённые префабы источников",
		["Source prefab block list"] = "Запрещённые префабы источников",
		["Dropped item block list"] = "Запрещённые выпадающие предметы",
		["Dungeon prefab allow list"] = "Разрешённые префабы подземелий",
		["Defeated enemies required"] = "Требуемый процент врагов",
		["Inspected chests required"] = "Требуемый процент сундуков",
		["Minimum observed chests"] = "Минимум найденных сундуков",
		["Dungeon inventory settle delay"] = "Задержка учёта подземелья",
		["Enemy respawn mode"] = "Режим респауна врагов",
		["Reopen on respawn"] = "Возвращать при респауне",
		["Manual dungeon toggle"] = "Ручная зачистка подземелья",
		["Automatic portal pins"] = "Автометки порталов",
		["Track ships"] = "Отслеживать корабли",
		["Track carts"] = "Отслеживать повозки",
		["Vehicle update interval"] = "Интервал обновления транспорта",
		["Vehicle move threshold"] = "Порог движения транспорта",
		["Resource merge distance"] = "Дистанция слияния ресурсов",
		["Dungeon merge distance"] = "Дистанция слияния подземелий",
		["Portal merge distance"] = "Дистанция слияния порталов",
		["Animation"] = "Режим анимации",
		["Pickable shimmer"] = "Подсветка собираемых ресурсов",
		["Pulse color"] = "Цвет пульсации",
		["Pulse interval"] = "Интервал пульсации",
		["Pulse duration"] = "Длительность пульсации",
		["Pulse intensity"] = "Яркость пульсации",
		["Sweep color"] = "Цвет переливания",
		["Sweep interval"] = "Интервал переливания",
		["Sweep speed"] = "Скорость переливания",
		["Sweep maximum duration"] = "Максимальная длительность переливания",
		["Sweep intensity"] = "Яркость переливания",
		["Radius"] = "Радиус",
		["Sweep width"] = "Ширина волны",
		["Sweep softness"] = "Мягкость волны",
		["X-ray through terrain"] = "X-ray сквозь землю",
		["X-ray toggle key"] = "Клавиша X-ray",
		["X-ray color"] = "Цвет X-ray",
		["X-ray intensity"] = "Яркость X-ray",
		["X-ray radius"] = "Радиус X-ray",
		["X-ray renderer budget"] = "Лимит рендереров X-ray",
		["X-ray resource draw budget"] = "Лимит отрисовки ресурсов X-ray",
		["Renderer budget"] = "Лимит рендереров",
		["Draw-command budget"] = "Лимит команд отрисовки",
		["Save debounce"] = "Задержка сохранения",
		["Fog pixels per packet"] = "Пикселей тумана в пакете",
		["Fog merge cells per frame"] = "Ячеек тумана за кадр",
		["Peer event limit"] = "Лимит событий игрока",
		["Pin adds per frame"] = "Добавлений меток за кадр",
		["Overlap counters"] = "Счётчики наложений",
		["Overlap distance"] = "Дистанция наложения",
		["State diagnostics on map"] = "Диагностика состояния на карте",
		["Detailed logging"] = "Подробный журнал",
		["Enable RavenMap. Requires a restart."] = "Включает RavenMap. Требуется перезапуск.",
		["Show names beside automatic pins. Local setting."] = "Показывает названия рядом с автометками. Локальная настройка.",
		["Show portal names independently. Local setting."] = "Показывает названия порталов независимо от других меток. Локальная настройка.",
		["Map-filter wheel speed in UI pixels per step."] = "Скорость колеса в окне фильтров, в пикселях за шаг.",
		["Merge explored fog into the shared server map."] = "Объединяет разведанный туман войны на общей карте сервера.",
		["Share automatic pins with every player."] = "Делится автометками со всеми игроками.",
		["Discovery radius for loaded resources; unloaded zones are never scanned."] = "Радиус обнаружения загруженных ресурсов; незагруженные зоны не сканируются.",
		["Discovery radius for loaded dungeons."] = "Радиус обнаружения загруженных подземелий.",
		["WishboneOnly is vanilla-like; Radius is automatic; Disabled never pins silver."] = "«Только с дужкой» работает как в ваниле; «По радиусу» — автоматически; «Выключено» — не отмечать серебро.",
		["Discover non-silver underground resources automatically instead of on detection or mining."] = "Автоматически обнаруживает подземные ресурсы, кроме серебра, не дожидаясь поиска или добычи.",
		["Server policy: track naturally spawned renewable and one-shot berries, mushrooms, plants and other Pickable objects."] = "Серверное правило: отслеживает естественно появившиеся возобновляемые и одноразовые ягоды, грибы, растения и другие собираемые объекты.",
		["Server discovery radius for loaded pickable plants; unloaded zones are never scanned."] = "Серверный радиус обнаружения загруженных собираемых растений; незагруженные зоны не сканируются.",
		["Server policy: cross out a renewable pickable after harvest and restore it when the game respawns it."] = "Серверное правило: зачёркивает возобновляемый объект после сбора и снимает зачёркивание, когда игра восстановит его.",
		["Server merge distance for equivalent pickable pins."] = "Серверная дистанция слияния одинаковых отметок собираемых объектов.",
		["Remove a vein pin after this share of its original amount is depleted."] = "Удаляет метку жилы после выработки указанной доли исходного объёма.",
		["Extra depletion required before another progress update."] = "Дополнительная выработка до следующего обновления прогресса.",
		["Minimum interval between ordinary updates for one resource."] = "Минимальный интервал между обычными обновлениями одного ресурса.",
		["Semicolon-separated source prefabs; SourcePrefab=ItemPrefab overrides inferred drops."] = "Префабы источников через точку с запятой; SourcePrefab=ItemPrefab переопределяет определённый предмет.",
		["Semicolon-separated prefabs never treated as resources."] = "Префабы через точку с запятой, которые никогда не считаются ресурсами.",
		["Ignore deposits whose inferred drops are only these item keys."] = "Игнорирует залежи, из которых определяются только перечисленные предметы.",
		["Semicolon-separated location prefabs always treated as clearable dungeons."] = "Префабы локаций через точку с запятой, всегда считающиеся зачищаемыми подземельями.",
		["Defeated share of observed enemies required before crossing out a dungeon."] = "Доля побеждённых обнаруженных врагов для зачёркивания подземелья.",
		["Observed-chest share required before crossing out a dungeon."] = "Доля осмотренных обнаруженных сундуков для зачёркивания подземелья.",
		["Minimum observed chests required for automatic clearing."] = "Минимум обнаруженных сундуков для автоматической отметки о зачистке.",
		["Delay before RavenMap requires two identical exact generator-volume snapshots for the current visit."] = "Задержка перед двумя одинаковыми точными снимками объёма генератора текущего посещения.",
		["Auto reopens an already cleared dungeon for a new wave only when a respawning spawner is present; Enabled always permits this; Disabled keeps cleared state."] = "«Авто» снимает зачёркивание уже зачищенного подземелья для новой волны только при наличии возобновляемого спаунера; «Включено» всегда разрешает это, а «Выключено» сохраняет зачистку.",
		["Remove crossed-out state when a respawn-capable dungeon gets a live enemy."] = "Снимает зачёркивание, когда в подземелье с респауном появляется живой враг.",
		["Hold this key and left-click a RavenMap dungeon icon to share a forced cleared/active state. Set None to disable."] = "Зажмите эту клавишу и щёлкните ЛКМ по значку подземелья RavenMap, чтобы принудительно и для всех переключить состояние зачистки. Значение None отключает функцию.",
		["Pin portals automatically and keep their tag current."] = "Автоматически отмечает порталы и обновляет их название.",
		["Track vanilla and modded Ship components."] = "Отслеживает ванильные и модифицированные компоненты Ship.",
		["Track vanilla and modded Vagon components."] = "Отслеживает ванильные и модифицированные компоненты Vagon.",
		["Position-report interval for loaded vehicles."] = "Интервал отправки позиции загруженного транспорта.",
		["Movement required before reporting a new vehicle position."] = "Минимальное движение до отправки новой позиции транспорта.",
		["Server merge distance for equivalent resource pins."] = "Серверная дистанция слияния одинаковых меток ресурсов.",
		["Server merge distance for equivalent dungeon pins."] = "Серверная дистанция слияния одинаковых меток подземелий.",
		["Server merge distance for equivalent portal pins."] = "Серверная дистанция слияния одинаковых меток порталов.",
		["Periodically highlight nearby visible resources and enabled Pickables without material instances."] = "Периодически подсвечивает ближайшие видимые ресурсы и включённые природные собираемые объекты без создания копий материалов.",
		["Sweep travels across highlighted geometry; Pulse brightens the whole object."] = "«Переливание» проходит волной по подсвечиваемой геометрии; «Пульсация» плавно подсвечивает весь объект.",
		["Apply the same Pulse or Sweep highlight to nearby loaded natural Pickables. Local setting."] = "Применяет ту же пульсацию или переливание к ближайшим загруженным природным собираемым ресурсам. Локальная настройка.",
		["Color used by the whole-object pulse."] = "Цвет пульсации, подсвечивающей весь объект.",
		["Delay between pulse effects."] = "Пауза между пульсациями.",
		["Duration of one smooth pulse."] = "Длительность одной плавной пульсации.",
		["Tint and HDR glow strength of the pulse."] = "Сила оттенка и HDR-свечения пульсации.",
		["Color of the soft wave travelling across highlighted geometry."] = "Цвет мягкой волны, проходящей по подсвечиваемой геометрии.",
		["Delay between sweep effects."] = "Пауза между переливаниями.",
		["World-space speed of the travelling wave."] = "Скорость движения волны в метрах игрового мира в секунду.",
		["Safety limit for one sweep; very large geometry still completes its exit."] = "Предельная длительность одного переливания; на очень большой геометрии волна всё равно полностью выходит за дальний край.",
		["Tint and HDR glow strength of the travelling wave."] = "Сила оттенка и HDR-свечения движущейся волны.",
		["Only loaded resources and enabled Pickables inside this radius may shimmer."] = "Переливаются только загруженные ресурсы и включённые собираемые объекты в этом радиусе.",
		["Relative width of the soft wave; the maximum covers almost the complete highlighted object."] = "Относительная ширина мягкой волны; максимальное значение покрывает почти весь подсвечиваемый объект.",
		["Softness of the moving wave; higher values remove the flat center and spread the fade across the whole effect."] = "Мягкость движущейся волны; большие значения убирают плоский центр и растягивают затухание на весь эффект.",
		["Enable local X-ray rendering. Its hotkey only changes temporary visibility while this setting is enabled."] = "Включает локальный X-ray. Горячая клавиша меняет только временную видимость, пока эта настройка включена.",
		["Toggle local X-ray visibility during gameplay. Works only when XrayEnabled is on; set None to disable."] = "Переключает локальную видимость X-ray во время игры. Работает только при включённом XrayEnabled; значение None отключает клавишу.",
		["Color used for vein geometry visible through terrain."] = "Цвет геометрии жилы, видимой сквозь землю.",
		["HDR brightness of X-ray vein geometry."] = "HDR-яркость геометрии жилы в режиме X-ray.",
		["Only already discovered loaded veins inside this local radius appear in X-ray."] = "В X-ray видны только уже обнаруженные и загруженные жилы в пределах этого локального радиуса.",
		["Total renderer budget for the current X-ray selection."] = "Общий лимит рендереров в текущей выборке X-ray.",
		["Hard resource draw-command limit for modded meshes with many submeshes."] = "Жёсткий лимит команд отрисовки ресурсов для модифицированных мешей с большим числом сабмешей.",
		["Hard total renderer limit for one complete shimmer batch."] = "Жёсткий общий лимит рендереров для одного полного цикла подсветки.",
		["Hard total draw-call limit for one shimmer frame, including modded multi-submesh objects."] = "Жёсткий общий лимит команд отрисовки для одного кадра подсветки, включая модифицированные объекты с несколькими сабмешами.",
		["Idle time after the last state change before saving; continuous changes are flushed periodically."] = "Время ожидания после последнего изменения; при непрерывных изменениях сохранение всё равно выполняется периодически.",
		["Hard fog-delta packet limit."] = "Жёсткий лимит изменений тумана в одном пакете.",
		["Shared-fog cells examined per frame; lower values reduce spikes."] = "Ячейки общего тумана, обрабатываемые за кадр; меньшее значение снижает скачки нагрузки.",
		["Server event-rate guard per peer."] = "Серверный лимит частоты событий для одного игрока.",
		["Frame budget for restoring or enabling automatic pins."] = "Кадровый лимит восстановления или включения автометок.",
		["Show local P/S counters for overlapping canonical pins and sources."] = "Показывает локальные счётчики P/S для наложившихся меток и источников.",
		["World-space grouping distance for overlap counters."] = "Дистанция группировки счётчиков наложения в игровом мире.",
		["Show local resource measurements and dungeon clearing blockers beside RavenMap pins. Local setting."] = "Показывает рядом с отметками RavenMap локальные измерения ресурсов и причины, мешающие зачистке подземелья. Локальная настройка.",
		["Log classification, deduplication and network details."] = "Записывает подробности классификации, дедупликации и сети."
	};

	internal static bool IsRussian(string language)
	{
		return string.Equals(language, "Russian", StringComparison.OrdinalIgnoreCase);
	}

	internal static string Localize(string english, bool russian)
	{
		if (!russian || string.IsNullOrEmpty(english))
		{
			return english ?? string.Empty;
		}
		if (!Russian.TryGetValue(english, out var value))
		{
			return english;
		}
		return value;
	}

	internal static bool HasRussian(string english)
	{
		if (!string.IsNullOrEmpty(english))
		{
			return Russian.ContainsKey(english);
		}
		return false;
	}

	internal unsafe static string EnumLabel(object value, bool russian)
	{
		//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_00ea: 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_00f3: Unknown result type (might be due to invalid IL or missing references)
		//IL_0111: Expected I4, but got Unknown
		if (value is SilverDiscoveryMode silverDiscoveryMode)
		{
			if (!russian)
			{
				if (silverDiscoveryMode != SilverDiscoveryMode.WishboneOnly)
				{
					return silverDiscoveryMode.ToString();
				}
				return "Wishbone only";
			}
			switch (silverDiscoveryMode)
			{
			case SilverDiscoveryMode.WishboneOnly:
				return "Только с дужкой";
			case SilverDiscoveryMode.Radius:
				return "По радиусу";
			case SilverDiscoveryMode.Disabled:
				return "Выключено";
			}
		}
		if (value is DungeonRespawnMode dungeonRespawnMode)
		{
			if (!russian)
			{
				return dungeonRespawnMode.ToString();
			}
			switch (dungeonRespawnMode)
			{
			case DungeonRespawnMode.Auto:
				return "Авто";
			case DungeonRespawnMode.Enabled:
				return "Включено";
			case DungeonRespawnMode.Disabled:
				return "Выключено";
			}
		}
		if (value is ShimmerAnimationMode shimmerAnimationMode)
		{
			if (!russian)
			{
				return shimmerAnimationMode.ToString();
			}
			switch (shimmerAnimationMode)
			{
			case ShimmerAnimationMode.Sweep:
				return "Переливание";
			case ShimmerAnimationMode.Pulse:
				return "Пульсация";
			}
		}
		if (value is KeyCode val)
		{
			if (!russian)
			{
				return ((object)(*(KeyCode*)(&val))/*cast due to .constrained prefix*/).ToString();
			}
			if ((int)val != 0)
			{
				return (val - 303) switch
				{
					5 => "Левый Alt", 
					4 => "Правый Alt", 
					3 => "Левый Ctrl", 
					2 => "Правый Ctrl", 
					1 => "Левый Shift", 
					0 => "Правый Shift", 
					_ => ((object)(*(KeyCode*)(&val))/*cast due to .constrained prefix*/).ToString(), 
				};
			}
			return "Отключено";
		}
		return null;
	}
}
internal sealed class ConfigurationManagerAttributes
{
	public string Category { get; set; }

	public string DispName { get; set; }

	public string Description { get; set; }

	public bool? IsAdvanced { get; set; }

	public int? Order { get; set; }

	public bool? Browsable { get; set; }

	internal string EnglishCategory { get; set; }

	internal string EnglishDispName { get; set; }

	internal string EnglishDescription { get; set; }

	internal bool HasCompleteRussianTranslation
	{
		get
		{
			if (ConfigText.HasRussian(EnglishCategory) && ConfigText.HasRussian(EnglishDispName))
			{
				return ConfigText.HasRussian(EnglishDescription);
			}
			return false;
		}
	}

	internal bool ApplyLanguage(string language)
	{
		bool russian = ConfigText.IsRussian(language);
		string text = ConfigText.Localize(EnglishCategory, russian);
		string text2 = ConfigText.Localize(EnglishDispName, russian);
		string text3 = ConfigText.Localize(EnglishDescription, russian);
		bool result = Category != text || DispName != text2 || Description != text3;
		Category = text;
		DispName = text2;
		Description = text3;
		return result;
	}
}
internal static class ConfigurationManagerIntegration
{
	private const string PluginGuid = "_shudnal.ConfigurationManager";

	private const string DrawerTypeName = "ConfigurationManager.SettingFieldDrawer";

	private static bool _russian;

	private static bool _refreshFailureReported;

	private static PropertyInfo _guiContentTextProperty;

	internal static void SetLanguage(string language)
	{
		_russian = ConfigText.IsRussian(language);
	}

	internal static string GetEnumLabel(object value)
	{
		return ConfigText.EnumLabel(value, _russian);
	}

	internal static bool TryInstallEnumLocalization(Harmony harmony)
	{
		//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00af: Expected O, but got Unknown
		if (harmony == null)
		{
			return false;
		}
		try
		{
			Type type = AccessTools.TypeByName("ConfigurationManager.SettingFieldDrawer");
			MethodInfo methodInfo = ((type == null) ? null : AccessTools.Method(type, "ObjectToGuiContent", new Type[1] { typeof(object) }, (Type[])null));
			MethodInfo methodInfo2 = AccessTools.Method(typeof(ConfigurationManagerIntegration), "EnumGuiContentPostfix", (Type[])null, (Type[])null);
			if (methodInfo == null || methodInfo2 == null)
			{
				return false;
			}
			_guiContentTextProperty = methodInfo.ReturnType.GetProperty("text", BindingFlags.Instance | BindingFlags.Public);
			if (_guiContentTextProperty == null || !_guiContentTextProperty.CanWrite)
			{
				return false;
			}
			harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			return true;
		}
		catch (Exception ex)
		{
			ManualLogSource log = RavenMapPlugin.Log;
			if (log != null)
			{
				log.LogWarning((object)("Configuration Manager enum localization was unavailable: " + ex.Message));
			}
			return false;
		}
	}

	internal static void RefreshIfInstalled()
	{
		try
		{
			Type type = AccessTools.TypeByName("ConfigurationManager.SettingFieldDrawer");
			if (type != null)
			{
				AccessTools.Method(type, "ClearCache", (Type[])null, (Type[])null)?.Invoke(null, null);
			}
			if (Chainloader.PluginInfos.TryGetValue("_shudnal.ConfigurationManager", out var value) && !((Object)(object)value.Instance == (Object)null))
			{
				AccessTools.Method(((object)value.Instance).GetType(), "BuildSettingList", (Type[])null, (Type[])null)?.Invoke(value.Instance, null);
				_refreshFailureReported = false;
			}
		}
		catch (Exception ex)
		{
			if (!_refreshFailureReported)
			{
				_refreshFailureReported = true;
				ManualLogSource log = RavenMapPlugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("Configuration Manager could not refresh localized RavenMap labels: " + ex.Message));
				}
			}
		}
	}

	private static void EnumGuiContentPostfix(object x, object __result)
	{
		string enumLabel = GetEnumLabel(x);
		if (!string.IsNullOrEmpty(enumLabel) && __result != null && _guiContentTextProperty != null)
		{
			_guiContentTextProperty.SetValue(__result, enumLabel, null);
		}
	}
}
internal sealed class ModConfig
{
	internal const string LegacyResourcePrefabAllowList = "MineRock_Copper;MineRock_Tin;mine_rock_iron;silvervein;MineRock_Obsidian;MineRock_Meteorite;Leviathan;giant_brain;softtissue_mineable;blackmarble_1;blackmarble_2;blackmarble_3;blackmarble_4;blackmarble_head_big01;blackmarble_head_big02;blackmarble_head01;blackmarble_head02;blackmarble_out_1;blackmarble_out_2;blackmarble_out_3;blackmarble_out_4;blackmarble_tip;MineRock_Lava;MineRock_Lava_big;coal_rock1_bal;coal_rock_nomoss_bal;MineRock_Coal_bal;MineRock_CoalSnow_bal;gold_Rock_bal;MineRock_Blackmetal_bal;MineRock_Borax_bal;MineRock_Cobalt_bal;MineRock_DarkIron_bal;MineRock_Lead_bal;MineRock_Zinc_bal;MineRock_Nickel_bal;rock_nickel_bal;rock_nickel_nomoss_bal;MineRock_Copper_bal;MineRock_IronNew_bal;MineRock_IronSnow_bal;MineRock_Guck_bal;rock_silver_small_bal;rock_silver_small_frac_bal;ClayDeposit_bal;ChitinDeposit_bal;bloodshard_deposit_bal;MineRock_MeteoriteNew_bal;Pickable_Clay_bal;Pickable_GuckSack_bal;Pickable_MeteoriteNew_bal;Pickable_MagmaStone_bal;Pickable_TinNew_bal;Pickable_MountainCaveCrystal_bal;deposit_jotunfinger_bal";

	internal const string DefaultResourcePrefabAllowList = "MineRock_Copper;rock4_copper;MineRock_Tin;mine_rock_iron;silvervein;MineRock_Obsidian;MineRock_Meteorite;Leviathan;giant_brain;softtissue_mineable;blackmarble_1;blackmarble_2;blackmarble_3;blackmarble_4;blackmarble_head_big01;blackmarble_head_big02;blackmarble_head01;blackmarble_head02;blackmarble_out_1;blackmarble_out_2;blackmarble_out_3;blackmarble_out_4;blackmarble_tip;MineRock_Lava;MineRock_Lava_big;coal_rock1_bal;coal_rock_nomoss_bal;MineRock_Coal_bal;MineRock_CoalSnow_bal;gold_Rock_bal;MineRock_Blackmetal_bal;MineRock_Borax_bal;MineRock_Cobalt_bal;MineRock_DarkIron_bal;MineRock_Lead_bal;MineRock_Zinc_bal;MineRock_Nickel_bal;rock_nickel_bal;rock_nickel_nomoss_bal;MineRock_Copper_bal;MineRock_IronNew_bal;MineRock_IronSnow_bal;MineRock_Guck_bal;rock_silver_small_bal;ClayDeposit_bal;ChitinDeposit_bal;MineRock_MeteoriteNew_bal;deposit_jotunfinger_bal";

	internal ConfigEntry<bool> Enabled;

	internal ConfigEntry<bool> ShowPinNames;

	internal ConfigEntry<bool> ShowPortalNames;

	internal ConfigEntry<float> VanillaPinIconScale;

	internal ConfigEntry<float> OtherPinIconScale;

	internal ConfigEntry<float> DungeonPinIconScale;

	internal ConfigEntry<float> PickablePinIconScale;

	internal ConfigEntry<float> ResourcePinIconScale;

	internal ConfigEntry<float> WorldLocationPinIconScale;

	internal ConfigEntry<float> FilterScrollSensitivity;

	internal ConfigEntry<bool> ShareFog;

	internal ConfigEntry<bool> SharePins;

	internal ConfigEntry<float> ResourceDiscoveryRadius;

	internal ConfigEntry<float> DungeonDiscoveryRadius;

	internal ConfigEntry<SilverDiscoveryMode> SilverMode;

	internal ConfigEntry<bool> AutoPinUndergroundResources;

	internal ConfigEntry<bool> TrackPickables;

	internal ConfigEntry<float> PickableDiscoveryRadius;

	internal ConfigEntry<bool> CrossOutRespawningPickables;

	internal ConfigEntry<float> ResourceRemovalPercent;

	internal ConfigEntry<float> ResourceProgressStepPercent;

	internal ConfigEntry<float> ResourceProgressMinInterval;

	internal ConfigEntry<string> ResourcePrefabAllowList;

	internal ConfigEntry<string> ResourcePrefabBlockList;

	internal ConfigEntry<string> ResourceItemBlockList;

	internal ConfigEntry<string> DungeonPrefabAllowList;

	internal ConfigEntry<float> RequiredDefeatedEnemiesPercent;

	internal ConfigEntry<float> DungeonChestInspectionPercent;

	internal ConfigEntry<float> DungeonCensusSettleSeconds;

	internal ConfigEntry<DungeonRespawnMode> DungeonRespawn;

	internal ConfigEntry<bool> ReopenDungeonOnRespawn;

	internal ConfigEntry<KeyCode> ManualDungeonToggleModifier;

	internal ConfigEntry<bool> AutoPinPortals;

	internal ConfigEntry<bool> TrackShips;

	internal ConfigEntry<bool> TrackCarts;

	internal ConfigEntry<float> VehicleUpdateInterval;

	internal ConfigEntry<float> VehicleMinimumMoveDistance;

	internal ConfigEntry<float> ResourceDedupeDistance;

	internal ConfigEntry<float> PickableDedupeDistance;

	internal ConfigEntry<float> DungeonDedupeDistance;

	internal ConfigEntry<float> PortalDedupeDistance;

	internal ConfigEntry<bool> ShimmerEnabled;

	internal ConfigEntry<ShimmerAnimationMode> ShimmerMode;

	internal ConfigEntry<bool> HighlightPickables;

	internal ConfigEntry<Color> PulseColor;

	internal ConfigEntry<float> PulseInterval;

	internal ConfigEntry<float> PulseDuration;

	internal ConfigEntry<float> PulseIntensity;

	internal ConfigEntry<Color> SweepColor;

	internal ConfigEntry<float> SweepInterval;

	internal ConfigEntry<float> SweepSpeed;

	internal ConfigEntry<float> SweepMaximumDuration;

	internal ConfigEntry<float> SweepIntensity;

	internal ConfigEntry<float> ShimmerRadius;

	internal ConfigEntry<float> SweepWaveWidth;

	internal ConfigEntry<float> SweepSoftness;

	internal ConfigEntry<bool> XrayEnabled;

	internal ConfigEntry<KeyCode> XrayToggleKey;

	internal ConfigEntry<Color> XrayColor;

	internal ConfigEntry<float> XrayIntensity;

	internal ConfigEntry<float> XrayRadius;

	internal ConfigEntry<int> XrayRendererBudget;

	internal ConfigEntry<int> XrayDrawCommandBudget;

	internal ConfigEntry<int> ShimmerRendererBudget;

	internal ConfigEntry<int> ShimmerDrawCommandBudget;

	internal ConfigEntry<float> SaveDebounceSeconds;

	internal ConfigEntry<int> MaxFogDeltaPixels;

	internal ConfigEntry<int> FogMergeCellsPerFrame;

	internal ConfigEntry<int> MaxNetworkEventsPerTenSeconds;

	internal ConfigEntry<int> MaxPinAddsPerFrame;

	internal ConfigEntry<bool> ShowPinOverlapDiagnostics;

	internal ConfigEntry<float> PinOverlapDiagnosticDistance;

	internal ConfigEntry<bool> ShowStateDiagnostics;

	internal ConfigEntry<bool> DetailedLogging;

	private const string InterfaceCategory = "01 - Interface";

	private const string SharingCategory = "02 - Sharing";

	private const string DiscoveryCategory = "03 - Discovery";

	private const string ResourcesCategory = "04 - Resources";

	private const string PickablesCategory = "04.1 - Pickables";

	private const string DungeonsCategory = "05 - Dungeons";

	private const string MarkersCategory = "06 - Markers";

	private const string DeduplicationCategory = "07 - Deduplication";

	private const string ShimmerCategory = "08 - Shimmer";

	private const string PulseCategory = "08.1 - Pulse";

	private const string SweepCategory = "08.2 - Sweep";

	private const string XrayCategory = "08.3 - X-ray";

	private const string PerformanceCategory = "09 - Performance";

	private const string DiagnosticsCategory = "10 - Diagnostics";

	private const int VisualSettingsVersion = 1;

	private static readonly FieldInfo[] ConfigEntryFields = (from field in typeof(ModConfig).GetFields(BindingFlags.Instance | BindingFlags.NonPublic)
		where typeof(ConfigEntryBase).IsAssignableFrom(field.FieldType)
		select field).ToArray();

	private static readonly FieldInfo ConfigDescriptionTextField = typeof(ConfigDescription).GetField("<Description>k__BackingField", BindingFlags.Instance | BindingFlags.NonPublic);

	private static bool _canRewriteConfigDescription = ConfigDescriptionTextField != null;

	internal bool AnyResourceVisualEnabled
	{
		get
		{
			if (!ShimmerEnabled.Value)
			{
				return XrayEnabled.Value;
			}
			return true;
		}
	}

	private static ConfigDescription Describe(string description, string category, string displayName, int order, AcceptableValueBase acceptableValues = null, bool advanced = false)
	{
		//IL_0052: Unknown result type (might be due to invalid IL or missing references)
		//IL_0058: Expected O, but got Unknown
		ConfigurationManagerAttributes configurationManagerAttributes = new ConfigurationManagerAttributes
		{
			EnglishCategory = category,
			EnglishDispName = displayName,
			EnglishDescription = description,
			Order = order,
			IsAdvanced = advanced
		};
		configurationManagerAttributes.ApplyLanguage("English");
		return new ConfigDescription(configurationManagerAttributes.Description, acceptableValues, new object[1] { configurationManagerAttributes });
	}

	internal static ModConfig Bind(ConfigFile file, string language = "English")
	{
		if (file == null)
		{
			throw new ArgumentNullException("file");
		}
		bool saveOnConfigSet = file.SaveOnConfigSet;
		file.SaveOnConfigSet = false;
		try
		{
			ModConfig result = BindCore(file, language);
			if (saveOnConfigSet)
			{
				file.Save();
			}
			return result;
		}
		finally
		{
			file.SaveOnConfigSet = saveOnConfigSet;
		}
	}

	private static ModConfig BindCore(ConfigFile file, string language)
	{
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: Expected O, but got Unknown
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_003d: 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
		//IL_0072: Unknown result type (might be due to invalid IL or missing references)
		//IL_0078: Expected O, but got Unknown
		//IL_0084: Unknown result type (might be due to invalid IL or missing references)
		//IL_008a: Expected O, but got Unknown
		//IL_0096: Unknown result type (might be due to invalid IL or missing references)
		//IL_009c: 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_00ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c0: Expected O, but got Unknown
		//IL_0120: Unknown result type (might be due to invalid IL or missing references)
		//IL_012a: Expected O, but got Unknown
		//IL_0191: Unknown result type (might be due to invalid IL or missing references)
		//IL_019b: Expected O, but got Unknown
		//IL_021b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0225: Expected O, but got Unknown
		//IL_0d65: Unknown result type (might be due to invalid IL or missing references)
		//IL_0e8f: Unknown result type (might be due to invalid IL or missing references)
		//IL_114f: Unknown result type (might be due to invalid IL or missing references)
		//IL_165a: Unknown result type (might be due to invalid IL or missing references)
		//IL_16af: Unknown result type (might be due to invalid IL or missing references)
		ConfigDefinition val = new ConfigDefinition("01 - General", "AutomaticPinIconScale");
		float value;
		bool flag = TryReadPersistedFloat(file, val, out value);
		ConfigDefinition val2 = new ConfigDefinition("01 - General", "ValheimLocationPinIconScale");
		float value2;
		bool flag2 = TryReadPersistedFloat(file, val2, out value2);
		bool[] array = ((IEnumerable<ConfigDefinition>)(object)new ConfigDefinition[6]
		{
			new ConfigDefinition("01 - General", "VanillaPinIconScale"),
			new ConfigDefinition("01 - General", "OtherPinIconScale"),
			new ConfigDefinition("01 - General", "DungeonPinIconScale"),
			new ConfigDefinition("01 - General", "PickablePinIconScale"),
			new ConfigDefinition("01 - General", "ResourcePinIconScale"),
			new ConfigDefinition("01 - General", "WorldLocationPinIconScale")
		}).Select((ConfigDefinition definition) => HasPersistedSetting(file, definition)).ToArray();
		ConfigEntry<float> val3 = file.Bind<float>(val, 0.7f, new ConfigDescription("Legacy RavenMap icon scale migration value.", (AcceptableValueBase)null, new object[1]
		{
			new ConfigurationManagerAttributes
			{
				Browsable = false,
				IsAdvanced = true,
				Order = int.MinValue
			}
		}));
		if (!flag)
		{
			value = val3.Value;
		}
		value = Mathf.Clamp(value, 0.5f, 3f);
		ConfigEntry<float> val4 = file.Bind<float>(val2, 0.7f, new ConfigDescription("Legacy Valheim location icon scale migration value.", (AcceptableValueBase)null, new object[1]
		{
			new ConfigurationManagerAttributes
			{
				Browsable = false,
				IsAdvanced = true,
				Order = int.MinValue
			}
		}));
		if (!flag2)
		{
			value2 = val4.Value;
		}
		value2 = Mathf.Clamp(value2, 0.5f, 3f);
		int num = ((!HasPersistedLegacyVisualSettings(file)) ? 1 : 0);
		ConfigEntry<int> val5 = file.Bind<int>("00 - Internal", "VisualSettingsVersion", num, new ConfigDescription("Internal RavenMap visual-settings migration version.", (AcceptableValueBase)null, new object[1]
		{
			new ConfigurationManagerAttributes
			{
				Browsable = false,
				IsAdvanced = true,
				Order = int.MinValue
			}
		}));
		ModConfig modConfig = new ModConfig
		{
			Enabled = file.Bind<bool>("01 - General", "Enabled", true, Describe("Enable RavenMap. Requires a restart.", "01 - Interface", "Enabled", 1000)),
			ShowPinNames = file.Bind<bool>("01 - General", "ShowAutomaticPinNames", false, Describe("Show names beside automatic pins. Local setting.", "01 - Interface", "Automatic pin names", 990)),
			ShowPortalNames = file.Bind<bool>("01 - General", "ShowPortalNames", true, Describe("Show portal names independently. Local setting.", "01 - Interface", "Portal names", 980)),
			VanillaPinIconScale = file.Bind<float>("01 - General", "VanillaPinIconScale", 0.7f, Describe("Local size multiplier for Valheim map marks, locations and Hildir pins.", "01 - Interface", "Vanilla pin size", 970, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 3f))),
			OtherPinIconScale = file.Bind<float>("01 - General", "OtherPinIconScale", 0.7f, Describe("Local size multiplier for portal, ship and cart pins.", "01 - Interface", "Other pin size", 960, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 3f))),
			DungeonPinIconScale = file.Bind<float>("01 - General", "DungeonPinIconScale", 0.7f, Describe("Local size multiplier for dungeon pins.", "01 - Interface", "Dungeon pin size", 955, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 3f))),
			PickablePinIconScale = file.Bind<float>("01 - General", "PickablePinIconScale", 0.7f, Describe("Local size multiplier for pickable-resource pins.", "01 - Interface", "Pickable pin size", 950, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 3f))),
			ResourcePinIconScale = file.Bind<float>("01 - General", "ResourcePinIconScale", 0.7f, Describe("Local size multiplier for deposit and vein pins.", "01 - Interface", "Resource pin size", 940, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 3f))),
			WorldLocationPinIconScale = file.Bind<float>("01 - General", "WorldLocationPinIconScale", 0.7f, Describe("Local visual size for More World Locations trader and port pins; built-in double size is normalized.", "01 - Interface", "More World Locations pin size", 930, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 3f))),
			FilterScrollSensitivity = file.Bind<float>("01 - General", "FilterScrollSpeed", 360f, Describe("Map-filter wheel speed in UI pixels per step.", "01 - Interface", "Filter scroll speed", 920, (AcceptableValueBase)(object)new AcceptableValueRange<float>(40f, 1200f))),
			ShareFog = file.Bind<bool>("02 - Multiplayer", "ShareFog", true, Describe("Merge explored fog into the shared server map.", "02 - Sharing", "Shared fog", 900)),
			SharePins = file.Bind<bool>("02 - Multiplayer", "ShareAutomaticPins", true, Describe("Share automatic pins with every player.", "02 - Sharing", "Shared automatic pins", 890)),
			ResourceDiscoveryRadius = file.Bind<float>("03 - Discovery", "ResourceRadius", 30f, Describe("Discovery radius for loaded resources; unloaded zones are never scanned.", "03 - Discovery", "Resource radius", 800, (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 128f))),
			DungeonDiscoveryRadius = file.Bind<float>("03 - Discovery", "DungeonRadius", 30f, Describe("Discovery radius for loaded dungeons.", "03 - Discovery", "Dungeon radius", 790, (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 256f))),
			SilverMode = file.Bind<SilverDiscoveryMode>("03 - Discovery", "SilverDiscovery", SilverDiscoveryMode.WishboneOnly, Describe("WishboneOnly is vanilla-like; Radius is automatic; Disabled never pins silver.", "03 - Discovery", "Silver discovery", 780)),
			AutoPinUndergroundResources = file.Bind<bool>("03 - Discovery", "AutoPinUndergroundResources", false, Describe("Discover non-silver underground resources automatically instead of on detection or mining.", "03 - Discovery", "Underground resources", 770)),
			ResourceRemovalPercent = file.Bind<float>("04 - Resources", "RemoveAfterDepletedPercent", 50f, Describe("Remove a vein pin after this share of its original amount is depleted.", "04 - Resources", "Remove after depletion", 700, (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 100f))),
			ResourceProgressStepPercent = file.Bind<float>("04 - Resources", "ProgressUpdateStepPercent", 2f, Describe("Extra depletion required before another progress update.", "04 - Resources", "Progress update step", 690, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 20f), advanced: true)),
			ResourceProgressMinInterval = file.Bind<float>("04 - Resources", "ProgressUpdateMinIntervalSeconds", 0.25f, Describe("Minimum interval between ordinary updates for one resource.", "04 - Resources", "Progress update interval", 680, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 2f), advanced: true)),
			ResourcePrefabAllowList = file.Bind<string>("04 - Resources", "PrefabAllowList", "MineRock_Copper;rock4_copper;MineRock_Tin;mine_rock_iron;silvervein;MineRock_Obsidian;MineRock_Meteorite;Leviathan;giant_brain;softtissue_mineable;blackmarble_1;blackmarble_2;blackmarble_3;blackmarble_4;blackmarble_head_big01;blackmarble_head_big02;blackmarble_head01;blackmarble_head02;blackmarble_out_1;blackmarble_out_2;blackmarble_out_3;blackmarble_out_4;blackmarble_tip;MineRock_Lava;MineRock_Lava_big;coal_rock1_bal;coal_rock_nomoss_bal;MineRock_Coal_bal;MineRock_CoalSnow_bal;gold_Rock_bal;MineRock_Blackmetal_bal;MineRock_Borax_bal;MineRock_Cobalt_bal;MineRock_DarkIron_bal;MineRock_Lead_bal;MineRock_Zinc_bal;MineRock_Nickel_bal;rock_nickel_bal;rock_nickel_nomoss_bal;MineRock_Copper_bal;MineRock_IronNew_bal;MineRock_IronSnow_bal;MineRock_Guck_bal;rock_silver_small_bal;ClayDeposit_bal;ChitinDeposit_bal;MineRock_MeteoriteNew_bal;deposit_jotunfinger_bal", Describe("Semicolon-separated source prefabs; SourcePrefab=ItemPrefab overrides inferred drops.", "04 - Resources", "Source prefab allow list", 670, null, advanced: true)),
			ResourcePrefabBlockList = file.Bind<string>("04 - Resources", "PrefabBlockList", "rock1_mountain;rock2_mountain;rock3_mountain", Describe("Semicolon-separated prefabs never treated as resources.", "04 - Resources", "Source prefab block list", 660, null, advanced: true)),
			ResourceItemBlockList = file.Bind<string>("04 - Resources", "DroppedItemBlockList", "$item_stone;$item_wood;$item_roundlog", Describe("Ignore deposits whose inferred drops are only these item keys.", "04 - Resources", "Dropped item block list", 650, null, advanced: true)),
			TrackPickables = file.Bind<bool>("03 - Discovery", "TrackRespawningPickables", true, Describe("Server policy: track naturally spawned renewable and one-shot berries, mushrooms, plants and other Pickable objects.", "04.1 - Pickables", "Enabled", 700)),
			PickableDiscoveryRadius = file.Bind<float>("03 - Discovery", "PickableRadius", 30f, Describe("Server discovery radius for loaded pickable plants; unloaded zones are never scanned.", "04.1 - Pickables", "Discovery radius", 690, (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 128f))),
			CrossOutRespawningPickables = file.Bind<bool>("04.1 - Pickables", "CrossOutRespawningPickables", true, Describe("Server policy: cross out a renewable pickable after harvest and restore it when the game respawns it.", "04.1 - Pickables", "Cross out after harvest", 680)),
			DungeonPrefabAllowList = file.Bind<string>("05 - Dungeons", "PrefabAllowList", "Crypt2;Crypt3;Crypt4;SunkenCrypt4;MountainCave02;Mistlands_DvergrTownEntrance1;Mistlands_DvergrTownEntrance2;Mistlands_DvergrTownEntrance3;BFD_Exterior;CD_Exterior1", Describe("Semicolon-separated location prefabs always treated as clearable dungeons.", "05 - Dungeons", "Dungeon prefab allow list", 620, null, advanced: true)),
			RequiredDefeatedEnemiesPercent = file.Bind<float>("05 - Dungeons", "RequiredDefeatedEnemiesPercent", 60f, Describe("Defeated share of observed enemies required before crossing out a dungeon.", "05 - Dungeons", "Defeated enemies required", 610, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f))),
			DungeonChestInspectionPercent = file.Bind<float>("05 - Dungeons", "RequiredInspectedChestsPercent", 60f, Describe("Observed-chest share required before crossing out a dungeon.", "05 - Dungeons", "Inspected chests required", 590, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f))),
			DungeonCensusSettleSeconds = file.Bind<float>("05 - Dungeons", "CensusSettleSeconds", 1.25f, Describe("Delay before RavenMap requires two identical exact generator-volume snapshots for the current visit.", "05 - Dungeons", "Dungeon inventory settle delay", 570, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 5f), advanced: true)),
			DungeonRespawn = file.Bind<DungeonRespawnMode>("05 - Dungeons", "EnemyRespawnMode", DungeonRespawnMode.Auto, Describe("Auto reopens an already cleared dungeon for a new wave only when a respawning spawner is present; Enabled always permits this; Disabled keeps cleared state.", "05 - Dungeons", "Enemy respawn mode", 560)),
			ReopenDungeonOnRespawn = file.Bind<bool>("05 - Dungeons", "ReopenWhenEnemiesRespawn", true, Describe("Remove crossed-out state when a respawn-capable dungeon gets a live enemy.", "05 - Dungeons", "Reopen on respawn", 550)),
			ManualDungeonToggleModifier = file.Bind<KeyCode>("05 - Dungeons", "ManualToggleModifier", (KeyCode)308, Describe("Hold this key and left-click a RavenMap dungeon icon to share a forced cleared/active state. Set None to disable.", "05 - Dungeons", "Manual dungeon toggle", 540)),
			AutoPinPortals = file.Bind<bool>("06 - Portals and vehicles", "AutoPinPortals", true, Describe("Pin portals automatically and keep their tag current.", "06 - Markers", "Automatic portal pins", 500)),
			TrackShips = file.Bind<bool>("06 - Portals and vehicles", "TrackShips", true, Describe("Track vanilla and modded Ship components.", "06 - Markers", "Track ships", 490)),
			TrackCarts = file.Bind<bool>("06 - Portals and vehicles", "TrackCarts", true, Describe("Track vanilla and modded Vagon components.", "06 - Markers", "Track carts", 480)),
			VehicleUpdateInterval = file.Bind<float>("06 - Portals and vehicles", "VehicleUpdateIntervalSeconds", 2f, Describe("Position-report interval for loaded vehicles.", "06 - Markers", "Vehicle update interval", 470, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 30f), advanced: true)),
			VehicleMinimumMoveDistance = file.Bind<float>("06 - Portals and vehicles", "VehicleMinimumMoveDistance", 2f, Describe("Movement required before reporting a new vehicle position.", "06 - Markers", "Vehicle move threshold", 460, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.25f, 25f), advanced: true)),
			ResourceDedupeDistance = file.Bind<float>("07 - Deduplication", "ResourceDistance", 4f, Describe("Server merge distance for equivalent resource pins.", "07 - Deduplication", "Resource merge distance", 400, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 20f))),
			PickableDedupeDistance = file.Bind<float>("07 - Deduplication", "PickableDistance", 4f, Describe("Server merge distance for equivalent pickable pins.", "04.1 - Pickables", "Merge distance", 670, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 20f))),
			DungeonDedupeDistance = file.Bind<float>("07 - Deduplication", "DungeonDistance", 12f, Describe("Server merge distance for equivalent dungeon pins.", "07 - Deduplication", "Dungeon merge distance", 390, (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 50f))),
			PortalDedupeDistance = file.Bind<float>("07 - Deduplication", "PortalDistance", 2f, Describe("Server merge distance for equivalent portal pins.", "07 - Deduplication", "Portal merge distance", 380, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.25f, 10f))),
			ShimmerEnabled = file.Bind<bool>("08 - Resource shimmer", "Enabled", true, Describe("Periodically highlight nearby visible resources and enabled Pickables without material instances.", "08 - Shimmer", "Enabled", 320)),
			ShimmerMode = file.Bind<ShimmerAnimationMode>("08 - Resource shimmer", "AnimationMode", ShimmerAnimationMode.Sweep, Describe("Sweep travels across highlighted geometry; Pulse brightens the whole object.", "08 - Shimmer", "Animation", 310)),
			HighlightPickables = file.Bind<bool>("08 - Resource shimmer", "HighlightPickables", false, Describe("Apply the same Pulse or Sweep highlight to nearby loaded natural Pickables. Local setting.", "08 - Shimmer", "Pickable shimmer", 300)),
			PulseColor = file.Bind<Color>("08 - Resource shimmer", "Color", new Color(1f, 1f, 1f, 0.2f), Describe("Color used by the whole-object pulse.", "08.1 - Pulse", "Pulse color", 300)),
			PulseInterval = file.Bind<float>("08 - Resource shimmer", "IntervalSeconds", 1f, Describe("Delay between pulse effects.", "08.1 - Pulse", "Pulse interval", 290, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 30f))),
			PulseDuration = file.Bind<float>("08 - Resource shimmer", "DurationSeconds", 1f, Describe("Duration of one smooth pulse.", "08.1 - Pulse", "Pulse duration", 280, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 5f))),
			PulseIntensity = file.Bind<float>("08 - Resource shimmer", "Intensity", 2f, Describe("Tint and HDR glow strength of the pulse.", "08.1 - Pulse", "Pulse intensity", 270, (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 10f))),
			SweepColor = file.Bind<Color>("08 - Resource shimmer", "SweepColor", new Color(1f, 1f, 1f, 0.2f), Describe("Color of the soft wave travelling across highlighted geometry.", "08.2 - Sweep", "Sweep color", 300)),
			SweepInterval = file.Bind<float>("08 - Resource shimmer", "SweepIntervalSeconds", 1f, Describe("Delay between sweep effects.", "08.2 - Sweep", "Sweep interval", 290, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 30f))),
			SweepSpeed = file.Bind<float>("08 - Resource shimmer", "SweepSpeedMetersPerSecond", 5f, Describe("World-space speed of the travelling wave.", "08.2 - Sweep", "Sweep speed", 280, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 30f))),
			SweepMaximumDuration = file.Bind<float>("08 - Resource shimmer", "SweepMaximumDurationSeconds", 3f, Describe("Safety limit for one sweep; very large geometry still completes its exit.", "08.2 - Sweep", "Sweep maximum duration", 270, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 30f))),
			SweepIntensity = file.Bind<float>("08 - Resource shimmer", "SweepIntensity", 3f, Describe("Tint and HDR glow strength of the travelling wave.", "08.2 - Sweep", "Sweep intensity", 260, (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 10f))),
			ShimmerRadius = file.Bind<float>("08 - Resource shimmer", "Radius", 20f, Describe("Only loaded resources and enabled Pickables inside this radius may shimmer.", "08 - Shimmer", "Radius", 260, (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 96f))),
			SweepWaveWidth = file.Bind<float>("08 - Resource shimmer", "WaveWidth", 1.5f, Describe("Relative width of the soft wave; the maximum covers almost the complete highlighted object.", "08.2 - Sweep", "Sweep width", 250, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 2f))),
			SweepSoftness = file.Bind<float>("08 - Resource shimmer", "SweepSoftness", 1f, Describe("Softness of the moving wave; higher values remove the flat center and spread the fade across the whole effect.", "08.2 - Sweep", "Sweep softness", 240, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f))),
			XrayEnabled = file.Bind<bool>("08 - Resource shimmer", "XrayEnabled", false, Describe("Enable local X-ray rendering. Its hotkey only changes temporary visibility while this setting is enabled.", "08.3 - X-ray", "X-ray through terrain", 240)),
			XrayToggleKey = file.Bind<KeyCode>("08 - Resource shimmer", "XrayToggleKey", (KeyCode)285, Describe("Toggle local X-ray visibility during gameplay. Works only when XrayEnabled is on; set None to disable.", "08.3 - X-ray", "X-ray toggle key", 235)),
			XrayColor = file.Bind<Color>("08 - Resource shimmer", "XrayColor", new Color(1f, 1f, 0f, 0.050980393f), Describe("Color used for vein geometry visible through terrain.", "08.3 - X-ray", "X-ray color", 230)),
			XrayIntensity = file.Bind<float>("08 - Resource shimmer", "XrayIntensity", 1f, Describe("HDR brightness of X-ray vein geometry.", "08.3 - X-ray", "X-ray intensity", 220, (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 10f))),
			XrayRadius = file.Bind<float>("08 - Resource shimmer", "XrayRadius", 10f, Describe("Only already discovered loaded veins inside this local radius appear in X-ray.", "08.3 - X-ray", "X-ray radius", 210, (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 96f))),
			XrayRendererBudget = file.Bind<int>("08 - Resource shimmer", "XrayMaxRenderers", 256, Describe("Total renderer budget for the current X-ray selection.", "08.3 - X-ray", "X-ray renderer budget", 200, (AcceptableValueBase)(object)new AcceptableValueRange<int>(16, 512), advanced: true)),
			XrayDrawCommandBudget = file.Bind<int>("08 - Resource shimmer", "XrayMaxDrawCommands", 1024, Describe("Hard resource draw-command limit for modded meshes with many submeshes.", "08.3 - X-ray", "X-ray resource draw budget", 190, (AcceptableValueBase)(object)new AcceptableValueRange<int>(64, 2048), advanced: true)),
			ShimmerRendererBudget = file.Bind<int>("08 - Resource shimmer", "MaxRenderersPerPulse", 256, Describe("Hard total renderer limit for one complete shimmer batch.", "08 - Shimmer", "Renderer budget", 200, (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 256), advanced: true)),
			ShimmerDrawCommandBudget = file.Bind<int>("08 - Resource shimmer", "MaxDrawCommandsPerPulse", 512, Describe("Hard total draw-call limit for one shimmer frame, including modded multi-submesh objects.", "08 - Shimmer", "Draw-command budget", 190, (AcceptableValueBase)(object)new AcceptableValueRange<int>(32, 2048), advanced: true)),
			SaveDebounceSeconds = file.Bind<float>("09 - Performance", "PersistenceDebounceSeconds", 10f, Describe("Idle time after the last state change before saving; continuous changes are flushed periodically.", "09 - Performance", "Save debounce", 200, (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 120f), advanced: true)),
			MaxFogDeltaPixels = file.Bind<int>("09 - Performance", "MaxFogPixelsPerPacket", 2048, Describe("Hard fog-delta packet limit.", "09 - Performance", "Fog pixels per packet", 190, (AcceptableValueBase)(object)new AcceptableValueRange<int>(64, 8192), advanced: true)),
			FogMergeCellsPerFrame = file.Bind<int>("09 - Performance", "FogMergeCellsPerFrame", 8192, Describe("Shared-fog cells examined per frame; lower values reduce spikes.", "09 - Performance", "Fog merge cells per frame", 180, (AcceptableValueBase)(object)new AcceptableValueRange<int>(4096, 262144), advanced: true)),
			MaxNetworkEventsPerTenSeconds = file.Bind<int>("09 - Performance", "MaxPeerEventsPerTenSeconds", 500, Describe("Server event-rate guard per peer.", "09 - Performance", "Peer event limit", 170, (AcceptableValueBase)(object)new AcceptableValueRange<int>(200, 5000), advanced: true)),
			MaxPinAddsPerFrame = file.Bind<int>("09 - Performance", "MaxPinAddsPerFrame", 96, Describe("Frame budget for restoring or enabling automatic pins.", "09 - Performance", "Pin adds per frame", 160, (AcceptableValueBase)(object)new AcceptableValueRange<int>(8, 512), advanced: true)),
			ShowPinOverlapDiagnostics = file.Bind<bool>("10 - Diagnostics", "ShowPinOverlapCounters", false, Describe("Show local P/S counters for overlapping canonical pins and sources.", "10 - Diagnostics", "Overlap counters", 100)),
			PinOverlapDiagnosticDistance = file.Bind<float>("10 - Diagnostics", "PinOverlapDistance", 1.5f, Describe("World-space grouping distance for overlap counters.", "10 - Diagnostics", "Overlap distance", 90, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 10f), advanced: true)),
			ShowStateDiagnostics = file.Bind<bool>("10 - Diagnostics", "ShowStateOnMap", false, Describe("Show local resource measurements and dungeon clearing blockers beside RavenMap pins. Local setting.", "10 - Diagnostics", "State diagnostics on map", 80)),
			DetailedLogging = file.Bind<bool>("10 - Diagnostics", "DetailedLogging", false, Describe("Log classification, deduplication and network details.", "10 - Diagnostics", "Detailed logging", 70, null, advanced: true))
		};
		ConfigEntry<float>[] array2 = new ConfigEntry<float>[6] { modConfig.VanillaPinIconScale, modConfig.OtherPinIconScale, modConfig.DungeonPinIconScale, modConfig.PickablePinIconScale, modConfig.ResourcePinIconScale, modConfig.WorldLocationPinIconScale };
		if (flag)
		{
			for (int num2 = 0; num2 < array2.Length; num2++)
			{
				if (!array[num2])
				{
					array2[num2].Value = value;
				}
			}
		}
		if (!array[2] && array[1])
		{
			modConfig.DungeonPinIconScale.Value = modConfig.OtherPinIconScale.Value;
		}
		if (!array[0] && flag2)
		{
			modConfig.VanillaPinIconScale.Value = value2;
		}
		file.Remove(val);
		file.Remove(val2);
		if (val5.Value < 1)
		{
			if (modConfig.ShimmerMode.Value == ShimmerAnimationMode.Sweep)
			{
				modConfig.SweepColor.Value = modConfig.PulseColor.Value;
				modConfig.SweepInterval.Value = modConfig.PulseInterval.Value;
				modConfig.SweepIntensity.Value = modConfig.PulseIntensity.Value;
				modConfig.PulseColor.Value = new Color(1f, 1f, 1f, 0.2f);
				modConfig.PulseInterval.Value = 1f;
				modConfig.PulseDuration.Value = 1f;
				modConfig.PulseIntensity.Value = 2f;
			}
			val5.Value = 1;
		}
		if (string.Equals(modConfig.ResourcePrefabAllowList.Value, "MineRock_Copper;MineRock_Tin;mine_rock_iron;silvervein;MineRock_Obsidian;MineRock_Meteorite;Leviathan;giant_brain;softtissue_mineable;blackmarble_1;blackmarble_2;blackmarble_3;blackmarble_4;blackmarble_head_big01;blackmarble_head_big02;blackmarble_head01;blackmarble_head02;blackmarble_out_1;blackmarble_out_2;blackmarble_out_3;blackmarble_out_4;blackmarble_tip;MineRock_Lava;MineRock_Lava_big;coal_rock1_bal;coal_rock_nomoss_bal;MineRock_Coal_bal;MineRock_CoalSnow_bal;gold_Rock_bal;MineRock_Blackmetal_bal;MineRock_Borax_bal;MineRock_Cobalt_bal;MineRock_DarkIron_bal;MineRock_Lead_bal;MineRock_Zinc_bal;MineRock_Nickel_bal;rock_nickel_bal;rock_nickel_nomoss_bal;MineRock_Copper_bal;MineRock_IronNew_bal;MineRock_IronSnow_bal;MineRock_Guck_bal;rock_silver_small_bal;rock_silver_small_frac_bal;ClayDeposit_bal;ChitinDeposit_bal;bloodshard_deposit_bal;MineRock_MeteoriteNew_bal;Pickable_Clay_bal;Pickable_GuckSack_bal;Pickable_MeteoriteNew_bal;Pickable_MagmaStone_bal;Pickable_TinNew_bal;Pickable_MountainCaveCrystal_bal;deposit_jotunfinger_bal", StringComparison.Ordinal))
		{
			modConfig.ResourcePrefabAllowList.Value = "MineRock_Copper;rock4_copper;MineRock_Tin;mine_rock_iron;silvervein;MineRock_Obsidian;MineRock_Meteorite;Leviathan;giant_brain;softtissue_mineable;blackmarble_1;blackmarble_2;blackmarble_3;blackmarble_4;blackmarble_head_big01;blackmarble_head_big02;blackmarble_head01;blackmarble_head02;blackmarble_out_1;blackmarble_out_2;blackmarble_out_3;blackmarble_out_4;blackmarble_tip;MineRock_Lava;MineRock_Lava_big;coal_rock1_bal;coal_rock_nomoss_bal;MineRock_Coal_bal;MineRock_CoalSnow_bal;gold_Rock_bal;MineRock_Blackmetal_bal;MineRock_Borax_bal;MineRock_Cobalt_bal;MineRock_DarkIron_bal;MineRock_Lead_bal;MineRock_Zinc_bal;MineRock_Nickel_bal;rock_nickel_bal;rock_nickel_nomoss_bal;MineRock_Copper_bal;MineRock_IronNew_bal;MineRock_IronSnow_bal;MineRock_Guck_bal;rock_silver_small_bal;ClayDeposit_bal;ChitinDeposit_bal;MineRock_MeteoriteNew_bal;deposit_jotunfinger_bal";
		}
		if (modConfig.PulseIntensity.Value < 1f)
		{
			modConfig.PulseIntensity.Value = 1f;
		}
		if (modConfig.SweepIntensity.Value < 1f)
		{
			modConfig.SweepIntensity.Value = 1f;
		}
		if (modConfig.XrayIntensity.Value < 1f)
		{
			modConfig.XrayIntensity.Value = 1f;
		}
		if (modConfig.ShimmerRendererBudget.Value == 48)
		{
			modConfig.ShimmerRendererBudget.Value = 256;
		}
		if (Mathf.Approximately(modConfig.FilterScrollSensitivity.Value, 28f) || Mathf.Approximately(modConfig.FilterScrollSensitivity.Value, 120f))
		{
			modConfig.FilterScrollSensitivity.Value = 360f;
		}
		if (modConfig.MaxNetworkEventsPerTenSeconds.Value < 200)
		{
			modConfig.MaxNetworkEventsPerTenSeconds.Value = 200;
		}
		if (modConfig.FogMergeCellsPerFrame.Value == 32768)
		{
			modConfig.FogMergeCellsPerFrame.Value = 8192;
		}
		modConfig.ApplyLocalization(language);
		return modConfig;
	}

	private static bool HasPersis