Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of RavenMap v1.9.15
RavenMap.dll
Decompiled a month ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.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