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 ConcernedCartographer v0.10.0
plugins/TheConcernedCat.ConcernedCartographer.dll
Decompiled 8 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.IO.Compression; using System.Net; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Text; using System.Text.RegularExpressions; using System.Threading; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Jotunn; using Jotunn.Entities; using Jotunn.Managers; using Microsoft.CodeAnalysis; using Splatform; using TheConcernedCat.ConcernedCartographer.Atlas; using TheConcernedCat.ConcernedCartographer.Map; using TheConcernedCat.ConcernedCartographer.Persistence; using TheConcernedCat.ConcernedCartographer.Reporting; using TheConcernedCat.ConcernedCartographer.Roads; using TheConcernedCat.ConcernedCartographer.Runtime; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("The Concerned Cat")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("Copyright © 2026 Eren Cansunar")] [assembly: AssemblyFileVersion("0.10.0.0")] [assembly: AssemblyInformationalVersion("0.10.0+a23bef007a75b84282c3aa0e0043b9be468f3301")] [assembly: AssemblyProduct("Concerned Cartographer")] [assembly: AssemblyTitle("TheConcernedCat.ConcernedCartographer")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/Weakened/ConcernedCatMods")] [assembly: AssemblyVersion("0.10.0.0")] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } } namespace TheConcernedCat.ConcernedCartographer { [BepInPlugin("com.theconcernedcat.valheim.concernedcartographer", "Concerned Cartographer", "0.10.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class Plugin : BaseUnityPlugin { public const string PluginGuid = "com.theconcernedcat.valheim.concernedcartographer"; public const string PluginName = "Concerned Cartographer"; public const string PluginVersion = "0.10.0"; private CartographerRuntime? _runtime; private CrashReportingHub? _crashHub; private void Awake() { CartographerSettings settings = CartographerSettings.Bind(((BaseUnityPlugin)this).Config); LocalizationPersistence.Initialize(((BaseUnityPlugin)this).Logger); try { _crashHub = new CrashReportingHub(settings, BuildCrashContext()); _crashHub.Attach(((BaseUnityPlugin)this).Logger); } catch (Exception exception) { _crashHub = null; ((BaseUnityPlugin)this).Logger.LogWarning((object)("Crash reporting unavailable this session: " + SafeLogText.Brief(exception))); } _runtime = new CartographerRuntime(settings, ((BaseUnityPlugin)this).Logger); MinimapManager.OnVanillaMapAvailable += HandleMapAvailable; MinimapManager.OnVanillaMapDataLoaded += HandleMapDataLoaded; CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new RoadToolsCommand(_runtime)); CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new PinToolsCommand(_runtime)); CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new AtlasToolsCommand(_runtime)); CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new SurveyToolsCommand(_runtime)); CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new RouteToolsCommand(_runtime)); CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new SyncToolsCommand(_runtime)); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Concerned Cartographer 0.10.0 loaded"); LogEnvironment(settings); } private static string ResolveInformationalVersion() { try { return typeof(Plugin).Assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?.InformationalVersion ?? "0.10.0"; } catch { return "0.10.0"; } } private CrashReportContext BuildCrashContext() { string text = ResolveInformationalVersion(); string bepInExVersion = "unknown"; string jotunnVersion = "unknown"; try { bepInExVersion = typeof(BaseUnityPlugin).Assembly.GetName().Version?.ToString() ?? "unknown"; jotunnVersion = typeof(Main).Assembly.GetName().Version?.ToString() ?? "unknown"; } catch { } return new CrashReportContext { Release = "ConcernedCartographer@" + text, ModVersion = "0.10.0", ValheimVersion = ResolveGameVersion(), UnityVersion = Application.unityVersion, BepInExVersion = bepInExVersion, JotunnVersion = jotunnVersion, RuntimeState = SampleRuntimeState }; } private static CrashReportRuntimeState SampleRuntimeState() { bool multiplayer = false; bool noMap = false; bool mapOpen = false; try { multiplayer = (Object)(object)ZNet.instance != (Object)null && ZNet.instance.GetPeers().Count > 0; } catch { } try { noMap = (Object)(object)ZoneSystem.instance != (Object)null && ZoneSystem.instance.GetGlobalKey("nomap"); } catch { } try { mapOpen = Minimap.IsOpen(); } catch { } return new CrashReportRuntimeState(multiplayer, noMap, mapOpen); } private void LogEnvironment(CartographerSettings settings) { try { string text = typeof(BaseUnityPlugin).Assembly.GetName().Version?.ToString() ?? "unknown"; string text2 = typeof(Main).Assembly.GetName().Version?.ToString() ?? "unknown"; string text3 = ResolveGameVersion(); ((BaseUnityPlugin)this).Logger.LogInfo((object)("Environment: Valheim " + text3 + ", Unity " + Application.unityVersion + ", BepInEx " + text + ", Jotunn " + text2 + ".")); ((BaseUnityPlugin)this).Logger.LogInfo((object)("Release: ConcernedCartographer@" + ResolveInformationalVersion() + ".")); ((BaseUnityPlugin)this).Logger.LogInfo((object)("Effective config (out-of-range values are clamped to documented ranges): " + $"Enabled={settings.Enabled.Value}, " + $"CaptureConstructionActions={settings.CaptureConstructionActions.Value}, " + $"ReconcileTerrainChanges={settings.ReconcileTerrainChanges.Value}, " + $"SampleIntervalSeconds={settings.SampleIntervalSeconds.Value}, " + $"MinimumPointSpacingMeters={settings.MinimumPointSpacingMeters.Value}, " + $"MaximumStrokeGapMeters={settings.MaximumStrokeGapMeters.Value}, " + $"DuplicateSuppressionMeters={settings.DuplicateSuppressionMeters.Value}, " + $"AutosaveIntervalSeconds={settings.AutosaveIntervalSeconds.Value}, " + $"PaintThreshold={settings.PaintThreshold.Value}, " + $"PaintSampleRadius={settings.PaintSampleRadius.Value}, " + $"LineWidthPixels={settings.LineWidthPixels.Value}, " + $"DebugLogging={settings.DebugLogging.Value}, " + $"DrawCalibrationMarkers={settings.DrawCalibrationMarkers.Value}.")); } catch (Exception exception) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not record environment versions: " + SafeLogText.Brief(exception))); } } private static string ResolveGameVersion() { try { Type typeFromHandle = typeof(Version); object obj = typeFromHandle.GetField("CurrentVersion", BindingFlags.Static | BindingFlags.Public)?.GetValue(null) ?? typeFromHandle.GetProperty("CurrentVersion", BindingFlags.Static | BindingFlags.Public)?.GetValue(null); if (obj != null) { return obj.ToString(); } MethodInfo[] methods = typeFromHandle.GetMethods(BindingFlags.Static | BindingFlags.Public); foreach (MethodInfo methodInfo in methods) { if (!(methodInfo.Name != "GetVersionString") && !(methodInfo.ReturnType != typeof(string))) { ParameterInfo[] parameters = methodInfo.GetParameters(); object[] array = new object[parameters.Length]; for (int j = 0; j < parameters.Length; j++) { array[j] = (parameters[j].HasDefaultValue ? parameters[j].DefaultValue : (parameters[j].ParameterType.IsValueType ? Activator.CreateInstance(parameters[j].ParameterType) : null)); } return (methodInfo.Invoke(null, array) as string) ?? "unknown"; } } } catch { } return "unknown"; } private void HandleMapAvailable() { _runtime?.OnMapAvailable(); } private void HandleMapDataLoaded() { _runtime?.OnMapDataReconstructed(); } private void Update() { _runtime?.Tick(Time.unscaledDeltaTime); } private void OnApplicationQuit() { _runtime?.SaveAll(); } private void OnDestroy() { MinimapManager.OnVanillaMapAvailable -= HandleMapAvailable; MinimapManager.OnVanillaMapDataLoaded -= HandleMapDataLoaded; _runtime?.Dispose(); _runtime = null; _crashHub?.Dispose(); _crashHub = null; } } } namespace TheConcernedCat.ConcernedCartographer.Runtime { internal sealed class AtlasToolsCommand : ConsoleCommand { private readonly CartographerRuntime _runtime; public override string Name => "cc_atlas"; public override string Help => "Concerned Cartographer atlas drawer and maintenance. Subcommands: status, query <text>, clear, pins on|off, cluster on|off, dirt on|off, paved on|off, view save|apply|del <name>, views, compat, backup, backups, restore <n>, support. Drawer panel: DrawerHotkey (default L) on the large map."; public AtlasToolsCommand(CartographerRuntime runtime) { _runtime = runtime; } public override void Run(string[] args, Terminal context) { string text; try { text = _runtime.ExecuteAtlasCommand(args); } catch (Exception ex) { text = "Atlas tool failed: " + ex.Message; } if (context != null) { context.AddString(text); } } public override List<string> CommandOptionList() { return new List<string> { "status", "query", "clear", "pins", "cluster", "dirt", "paved", "view", "views", "compat", "backup", "backups", "restore", "support" }; } } internal sealed class CartographerRuntime : IDisposable { private readonly CartographerSettings _settings; private readonly ManualLogSource _log; private readonly RoadPersistence _persistence; private readonly PinPersistence _pinPersistence; private readonly GroundPaintProbe _probe; private readonly RoadOverlayRenderer _renderer; private readonly ConstructionCapture _constructionCapture; private readonly PinAdapter _pinAdapter; private readonly RateLimitedLog _rateLimited; private readonly ModalInputBlock _textFocusBlock = new ModalInputBlock((Action<bool>)GUIManager.BlockInput); private const float RedrawDebounceSeconds = 0.5f; private bool _redrawPending; private float _redrawElapsed; private RoadAtlas _atlas = new RoadAtlas(); private TerrainIntentMask _terrainIntent = new TerrainIntentMask(); private readonly TerrainIntentPersistence _terrainIntentPersistence; private RoadObservationPipeline? _pipeline; private RoadAtlasEditor? _editor; private RoadSurveyor? _surveyor; private PinStore _pinStore = new PinStore(); private PinCommandHandler? _pinCommands; private readonly PinWorkbenchPanel _workbenchPanel; private readonly PinDisplayController _displayController; private readonly AtlasDrawerPanel _drawerPanel; private readonly SavedViewPersistence _savedViewPersistence; private SavedViewStore _savedViews = new SavedViewStore(); private readonly MapUiCoordinator _mapUi; private readonly CrashConsentPanel _consentPanel; private bool _consentPromptChecked; private readonly PinPalettePanel _palettePanel; private readonly RoutesPanel _routesPanel; private readonly SurveyPanel _surveyPanel; private readonly SharePanel _sharePanel; private readonly SettingsPanel _settingsPanel; private readonly SystemMarkersPanel _systemMarkersPanel; private int _drawerToken; private int _paletteToken; private int _routesToken; private int _surveyToken; private int _shareToken; private int _settingsToken; private int _systemMarkersToken; private int _workbenchToken; private readonly QuickPinInputGate _quickPinGate = new QuickPinInputGate(); private readonly PaletteBirthTracker<PinData> _birthTracker = new PaletteBirthTracker<PinData>(); private float _hintElapsed; private readonly OrphanChromeSweep _chromeSweep = new OrphanChromeSweep(); private string _lastChromeSweepDiagnostics = ""; private readonly DefaultPanelRule _defaultPanel = new DefaultPanelRule(); private const float ContextGraceSeconds = 1.5f; private float _contextGrace; private readonly QuickPinCapture _quickPinCapture; private readonly SurveyEngine _surveyEngine = new SurveyEngine(); private readonly SurveyScanner _surveyScanner; private readonly SurveyRulePersistence _surveyRulePersistence; private readonly SurveyRejectedPersistence _surveyRejectedPersistence; private readonly RoutePersistence _routePersistence; private readonly RouteOverlayRenderer _routeRenderer; private readonly OverlayPanelRelabel _overlayRelabel; private float _relabelElapsed; private RouteStore _routeStore = new RouteStore(); private RouteCommandHandler? _routeCommands; private bool _routeRedrawPending; private float _routeRedrawElapsed; private readonly SyncInbox _syncInbox = new SyncInbox(); private readonly SyncTransport _syncTransport; private string _authorId = ""; private readonly CompatibilityRegistry _compatibility = new CompatibilityRegistry(); private readonly AtlasBackupTools _backupTools; private long? _worldUid; private bool _mapReady; private float _autosaveElapsed; private bool _disposed; private readonly MapSessionTracker _mapSession = new MapSessionTracker(); private string _lastRailDiagnostics = ""; private bool _onboardingChecked; private string _lastToolSummary = ""; internal PinStore Pins => _pinStore; internal PinAdapter PinAdapter => _pinAdapter; internal PinCommandHandler? PinCommands => _pinCommands; public CartographerRuntime(CartographerSettings settings, ManualLogSource log) { _settings = settings; _log = log; _persistence = new RoadPersistence(log); _terrainIntentPersistence = new TerrainIntentPersistence(log); _pinPersistence = new PinPersistence(log); _probe = new GroundPaintProbe(settings, log); _renderer = new RoadOverlayRenderer(settings, log); _rateLimited = new RateLimitedLog(log, 5f); _pinAdapter = new PinAdapter(log); _workbenchPanel = new PinWorkbenchPanel(log); _displayController = new PinDisplayController(log); _savedViewPersistence = new SavedViewPersistence(log); _savedViews = _savedViewPersistence.Load(); _drawerPanel = new AtlasDrawerPanel(log); WireDrawer(); _mapUi = new MapUiCoordinator(log); _consentPanel = new CrashConsentPanel(log, settings); _palettePanel = new PinPalettePanel(log); _routesPanel = new RoutesPanel(log, () => _routeCommands); _surveyPanel = new SurveyPanel(log, settings, ExecuteSurveyCommand, () => _surveyEngine.Observations, () => _surveyEngine, () => _surveyScanner); _sharePanel = new SharePanel(log, ExecuteSyncCommand, delegate { List<string> list = new List<string>(); foreach (SyncInbox.Envelope envelope in _syncInbox.Envelopes) { list.Add(envelope.AuthorName); } return list; }); _settingsPanel = new SettingsPanel(log, ExecuteAtlasCommand, ExecuteRoadCommand, delegate { _consentPanel.ShowSettings(); }); _systemMarkersPanel = new SystemMarkersPanel(log); _drawerToken = _mapUi.RegisterSurface(() => _drawerPanel.IsVisible, _drawerPanel.Hide); _paletteToken = _mapUi.RegisterSurface(() => _palettePanel.IsVisible, _palettePanel.Hide); _routesToken = _mapUi.RegisterSurface(() => _routesPanel.IsVisible, _routesPanel.Hide); _surveyToken = _mapUi.RegisterSurface(() => _surveyPanel.IsVisible, _surveyPanel.Hide); _shareToken = _mapUi.RegisterSurface(() => _sharePanel.IsVisible, _sharePanel.Hide); _settingsToken = _mapUi.RegisterSurface(() => _settingsPanel.IsVisible, _settingsPanel.Hide); _systemMarkersToken = _mapUi.RegisterSurface(() => _systemMarkersPanel.IsVisible, _systemMarkersPanel.Hide); _workbenchToken = _mapUi.RegisterSurface(() => _workbenchPanel.IsVisible, _workbenchPanel.Close); _mapUi.AtlasClicked = delegate { _mapUi.OpenExclusive(_drawerToken, ToggleDrawer); }; _mapUi.MarkersClicked = delegate { if (PaletteActive()) { _palettePanel.UiScale = _settings.UiScale.Value; _palettePanel.EnsureBuilt(); _mapUi.OpenExclusive(_paletteToken, _palettePanel.Toggle); } else { Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)1, "The enhanced marker palette is disabled (setting or a conflicting pin manager); the vanilla selector is shown instead.", 0, (Sprite)null); } } }; _mapUi.RoutesClicked = delegate { OpenSidePanel(_routesToken, _routesPanel); }; _mapUi.SurveyClicked = delegate { OpenSidePanel(_surveyToken, _surveyPanel); }; _mapUi.ShareClicked = delegate { OpenSidePanel(_shareToken, _sharePanel); }; _mapUi.SettingsClicked = delegate { OpenSidePanel(_settingsToken, _settingsPanel); }; _mapUi.QuickPinClicked = ArmQuickPin; _drawerPanel.PrivacyClicked = delegate { _consentPanel.ShowSettings(); }; _drawerPanel.SystemMarkersClicked = delegate { OpenSidePanel(_systemMarkersToken, _systemMarkersPanel); }; MapInputGate.Install(log); PlayerInputGate.Install(log); PlayerInputGate.SuppressAttack = () => _quickPinGate.SuppressAttack(Time.frameCount); PlayerInputGate.SuppressMenu = () => _quickPinGate.SuppressMenu(Time.frameCount); PinDeletionWatch.Install(log); PinDeletionWatch.ExplicitDelete = HandleExplicitVanillaDelete; MapInputGate.WheelGuard = () => Minimap.IsOpen() && (MapPointerGuard.IsPointerOverCcUi(Vector2.op_Implicit(Input.mousePosition)) || CcTextFocus.AnyFieldFocused()); MapPointerGuard.Clear(); MapPointerGuard.RegisterWidget(() => _mapUi.ToolbarObject); MapPointerGuard.RegisterWidget(() => _mapUi.ContextButtonObject); MapPointerGuard.RegisterWidget(() => _palettePanel.PanelObject); _palettePanel.IconChosen = delegate(IconRegistry.IconDefinition definition) { MinimapReflection.TrySelectIcon(definition.VanillaType); _birthTracker.Arm(definition.Id, definition.DefaultCategory); }; _palettePanel.SelectionCleared = delegate { _birthTracker.Disarm(); }; _quickPinCapture = new QuickPinCapture(settings, log); _surveyRulePersistence = new SurveyRulePersistence(log); _surveyRejectedPersistence = new SurveyRejectedPersistence(log); _surveyEngine.Rules = _surveyRulePersistence.LoadOrCreate(); _surveyScanner = new SurveyScanner(settings, log); _routePersistence = new RoutePersistence(log); _routeRenderer = new RouteOverlayRenderer(settings, log); _overlayRelabel = new OverlayPanelRelabel(log); _renderer.UserToggledOverlay += delegate(RoadKind kind, bool enabled) { if (kind == RoadKind.Dirt) { _settings.DrawerShowDirt.Value = enabled; } else { _settings.DrawerShowPaved.Value = enabled; } }; _routeRenderer.UserToggled += delegate(bool enabled) { _renderer.SetRouteVectorVisible(enabled); }; _authorId = AuthorIdentity.Get(log); _syncTransport = new SyncTransport(log, _syncInbox) { LocalAuthorId = _authorId }; _backupTools = new AtlasBackupTools(log); _constructionCapture = new ConstructionCapture(log); _constructionCapture.OperationCaptured += HandleTerrainOperation; } public void OnMapAvailable() { if (_disposed) { return; } if (!WorldContext.TryGetWorldUid(out var uid)) { _log.LogWarning((object)"Map became available before a world UID could be resolved; waiting for the next map event."); _mapReady = false; return; } SwitchWorld(uid); _mapReady = true; _log.LogInfo((object)string.Format("Map session lifecycle: generation {0} (map-available).", _mapSession.NoteTransition("map-available"))); _renderer.ResetMapSession(); _routeRenderer.ResetMapSession(); CcIconSprites.ResetSession(); _renderer.RedrawAll(_atlas); _pinAdapter.ReconcileOnMapReady(_pinStore); _mapSession.NoteBound(); _renderer.SetOverlayEnabled(RoadKind.Dirt, _settings.DrawerShowDirt.Value); _renderer.SetOverlayEnabled(RoadKind.Paved, _settings.DrawerShowPaved.Value); _displayController.ShowPins = _settings.DrawerShowPins.Value; _displayController.ClusterEnabled = _settings.DrawerCluster.Value; _displayController.Apply(_pinStore, _pinAdapter); _routeRenderer.RedrawAll(_routeStore); _renderer.MarkVectorDataDirty(); _syncTransport.EnsureRegistered(); _compatibility.Evaluate(_log); ShowOnboardingOnce(); if (_settings.DrawCalibrationMarkers.Value) { _renderer.DrawCalibrationMarkers(); } _log.LogInfo((object)$"Road atlas ready: {_atlas.Strokes.Count} stroke(s), {_atlas.PointCount} point(s)."); } public void OnMapDataReconstructed() { if (!_disposed) { if (!_mapReady) { OnMapAvailable(); return; } _log.LogInfo((object)string.Format("Map session lifecycle: generation {0} (map-data-loaded).", _mapSession.NoteTransition("map-data-loaded"))); _pinAdapter.ReconcileOnMapReady(_pinStore, "map-data-loaded"); _mapSession.NoteBound(); ReapplyDisplay(); } } private void HandleExplicitVanillaDelete(PinData pin) { if (!_disposed && _mapReady) { _pinAdapter.HandleExplicitVanillaDelete(_pinStore, pin); } } public void Tick(float unscaledDeltaTime) { //IL_0209: Unknown result type (might be due to invalid IL or missing references) //IL_026a: Unknown result type (might be due to invalid IL or missing references) //IL_026f: Unknown result type (might be due to invalid IL or missing references) //IL_021b: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_03c8: Unknown result type (might be due to invalid IL or missing references) //IL_0394: Unknown result type (might be due to invalid IL or missing references) //IL_0497: Unknown result type (might be due to invalid IL or missing references) //IL_048b: Unknown result type (might be due to invalid IL or missing references) //IL_04a5: Unknown result type (might be due to invalid IL or missing references) //IL_04aa: Unknown result type (might be due to invalid IL or missing references) //IL_04bc: Unknown result type (might be due to invalid IL or missing references) //IL_04c3: Unknown result type (might be due to invalid IL or missing references) //IL_04ca: Unknown result type (might be due to invalid IL or missing references) if (_disposed) { return; } _workbenchPanel.HandleFrame(); _consentPanel.HandleFrame(); _routesPanel.HandleFrame(); _surveyPanel.HandleFrame(); _sharePanel.HandleFrame(); _settingsPanel.HandleFrame(); _systemMarkersPanel.HandleFrame(); _palettePanel.HandleFrame(); if (!Minimap.IsOpen()) { MapInputGate.ConsumeClicks = false; } if (!_settings.Enabled.Value || !_mapReady || _surveyor == null) { MapInputGate.ConsumeClicks = false; _textFocusBlock.Release(); _quickPinGate.Disarm(); if (!_settings.Enabled.Value) { _renderer.EnsureTextureFallback(); _routeRenderer.TickVisibility(vectorRoutesActive: false); _overlayRelabel.Restore(); } if (Minimap.IsOpen()) { EnforceVanillaPaletteVisibility(); _palettePanel.SetUnavailable(); } if (_mapUi.AnySurfaceVisible) { _mapUi.CloseAllSurfaces(); } return; } _drawerPanel.HandleFrame(); bool flag = CcTextFocus.AnyFieldFocused(); if (flag) { _textFocusBlock.Acquire(); } else { _textFocusBlock.Release(); } if (!Minimap.IsOpen() && !Minimap.InTextInput() && !flag) { if (_quickPinGate.Armed) { switch (_quickPinGate.HandleFrame(Time.frameCount, Input.GetKeyDown((KeyCode)27), Input.GetMouseButtonDown(0) || ((int)_settings.QuickPinHotkey.Value != 0 && Input.GetKeyDown(_settings.QuickPinHotkey.Value)) || GamepadDown(_settings.WorkbenchGamepadButton.Value))) { case QuickPinInputGate.FrameAction.Cancel: { Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)1, AtlasStrings.Get("quickpin.cancelled"), 0, (Sprite)null); } break; } case QuickPinInputGate.FrameAction.Capture: CaptureQuickPin(); break; } } else if ((int)_settings.QuickPinHotkey.Value != 0 && Input.GetKeyDown(_settings.QuickPinHotkey.Value)) { CaptureQuickPin(); } } if (!Minimap.IsOpen()) { _defaultPanel.NoteMapClosed(); } if (Minimap.IsOpen() && !Minimap.InTextInput() && !flag) { _mapUi.EnsureBuilt(((object)_settings.DrawerHotkey.Value/*cast due to .constrained prefix*/).ToString()); if (!_consentPromptChecked) { _consentPromptChecked = true; if (_consentPanel.NeedsFirstRunPrompt) { _consentPanel.ShowFirstRun(); } } if (PaletteActive()) { _palettePanel.UiScale = _settings.UiScale.Value; _palettePanel.EnsureBuilt(); } else { _palettePanel.SetUnavailable(); } if (_defaultPanel.IsArmed && _defaultPanel.ShouldAutoOpen(PaletteActive() && !_mapUi.HasFailed && AtlasAccessAllowed(out string _), _mapUi.AnySurfaceVisible)) { _palettePanel.UiScale = _settings.UiScale.Value; _palettePanel.EnsureBuilt(); _mapUi.OpenExclusive(_paletteToken, delegate { if (!_palettePanel.IsVisible) { _palettePanel.Toggle(); } }); } UpdateEditHint(unscaledDeltaTime); if (_pinCommands != null && !_workbenchPanel.IsVisible && (Input.GetKeyDown(_settings.WorkbenchHotkey.Value) || GamepadDown(_settings.WorkbenchGamepadButton.Value))) { OpenWorkbenchAtCursor(); } if (Input.GetKeyDown(_settings.DrawerHotkey.Value) || GamepadDown(_settings.DrawerGamepadButton.Value)) { _mapUi.OpenExclusive(_drawerToken, ToggleDrawer); } if (_displayController.ZoomTierChanged()) { _displayController.Apply(_pinStore, _pinAdapter); } bool flag2 = (MapInputGate.ConsumeClicks = _routeCommands != null && _routeCommands.Mode != RouteCommandHandler.MapMode.None && _routeCommands.UiModeOwned); if (flag2) { MinimapReflection.TrySuppressMapDragThisFrame(); } if (_routeCommands != null && _routeCommands.Mode != RouteCommandHandler.MapMode.None && (flag2 || Input.GetKey(_settings.RouteDrawModifier.Value)) && MinimapReflection.TryScreenToWorldPoint(Input.mousePosition, out var worldPosition)) { bool flag3 = MapPointerGuard.IsPointerOverCcUi(Vector2.op_Implicit(Input.mousePosition)); _routeCommands.HandleMapFrame(new RoadPoint(worldPosition.x, worldPosition.y, worldPosition.z), Input.GetMouseButton(0) && !flag3, Input.GetMouseButtonDown(0) && !flag3); } } _routeRedrawElapsed += unscaledDeltaTime; if (_routeRedrawPending && _routeRedrawElapsed >= 0.5f) { _routeRedrawElapsed = 0f; _routeRedrawPending = false; _routeRenderer.RedrawAll(_routeStore); _renderer.MarkVectorDataDirty(); } if (!WorldContext.TryGetWorldUid(out var uid) || _worldUid != uid) { _mapReady = false; _log.LogInfo((object)string.Format("Map session lifecycle: generation {0} (world-unloaded).", _mapSession.NoteTransition("world-unloaded"))); _workbenchPanel.Close(); _mapUi.CloseAllSurfaces(); _drawerPanel.FlushPosition(); MapInputGate.ConsumeClicks = false; _textFocusBlock.Release(); _quickPinGate.Disarm(); _pipeline?.EndAllStrokes(); _displayController.Reset(); _mapUi.Reset(); _palettePanel.Reset(); _chromeSweep.RestoreAll(); _birthTracker.Reset(); _pinAdapter.Reset(); SaveIfDirty(); SavePinsSnapshot(); return; } _surveyor.Tick(unscaledDeltaTime); _renderer.TickVectorLayer(unscaledDeltaTime, _atlas, _routeStore); _routeRenderer.TickVisibility(_renderer.VectorLayerActive); _relabelElapsed += unscaledDeltaTime; if (_relabelElapsed >= 1f) { _relabelElapsed = 0f; if (Minimap.IsOpen()) { _overlayRelabel.EnsureApplied(); } } _surveyScanner.Tick(unscaledDeltaTime, _surveyEngine, _pinStore); if (_settings.EnhancedPinPalette.Value && MinimapReflection.TryGetNamePin(out PinData namePin)) { PinData val = _birthTracker.Observe(namePin); if (val != null) { HandlePaletteBirth(val); } if (namePin != null && _birthTracker.IsArmed) { _pinAdapter.ApplyImmediateSprite(namePin, _birthTracker.IconId); } } _redrawElapsed += unscaledDeltaTime; if (_redrawPending && _redrawElapsed >= 0.5f) { _redrawPending = false; _redrawElapsed = 0f; _renderer.RedrawAll(_atlas); } _autosaveElapsed += unscaledDeltaTime; if (_autosaveElapsed >= _settings.AutosaveIntervalSeconds.Value) { _autosaveElapsed = 0f; SaveIfDirty(); _pinAdapter.AbsorbVanillaChanges(_pinStore); if (_pinAdapter.NeedsRebind && _pinAdapter.IsOperational) { _pinAdapter.ReconcileOnMapReady(_pinStore, "rendering-loss-repair"); _mapSession.NoteBound(); ReapplyDisplay(); } _pinPersistence.FlushJournal(); _routePersistence.FlushJournal(); SaveRejectedIfDirty(); } } internal string ExecutePinCommand(string[] args) { //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) if (!AtlasAccessAllowed(out string denial)) { return denial; } if (_disposed || !_mapReady || _pinCommands == null) { return "Concerned Cartographer: no world is loaded yet."; } Player localPlayer = Player.m_localPlayer; if (localPlayer == null) { return "Concerned Cartographer: no local player."; } if (args.Length != 0 && string.Equals(args[0], "edit", StringComparison.OrdinalIgnoreCase)) { OpenWorkbenchNear(((Component)localPlayer).transform.position); return "Opening the Pin Workbench for the nearest pin."; } return _pinCommands.Execute(args, ((Component)localPlayer).transform.position); } private void WireDrawer() { _drawerPanel.LoadPosition = () => _settings.DrawerPanelPosition.Value; _drawerPanel.PositionCaptured = delegate(string stored) { _settings.DrawerPanelPosition.Value = stored; }; _drawerPanel.DirtToggled = delegate(bool value) { _settings.DrawerShowDirt.Value = value; _renderer.SetOverlayEnabled(RoadKind.Dirt, value); }; _drawerPanel.PavedToggled = delegate(bool value) { _settings.DrawerShowPaved.Value = value; _renderer.SetOverlayEnabled(RoadKind.Paved, value); }; _drawerPanel.PinsToggled = delegate(bool value) { _settings.DrawerShowPins.Value = value; _displayController.ShowPins = value; ReapplyDisplay(); }; _drawerPanel.ClusterToggled = delegate(bool value) { _settings.DrawerCluster.Value = value; _displayController.ClusterEnabled = value; ReapplyDisplay(); }; _drawerPanel.QueryApplied = delegate(string query) { _displayController.SetQuery(query); ReapplyDisplay(); }; _drawerPanel.ViewSaved = delegate(string name) { _savedViews.Save(new SavedView(name, _displayController.QueryText, _settings.DrawerShowDirt.Value, _settings.DrawerShowPaved.Value, _displayController.ShowPins, _displayController.ClusterEnabled)); _savedViewPersistence.Save(_savedViews); }; _drawerPanel.ViewApplied = delegate(string name) { ApplySavedView(name); }; _drawerPanel.ResultClicked = OpenWorkbenchForId; _drawerPanel.StatusLine = () => $"{_displayController.VisibleCount} shown · {_displayController.HiddenByFilter} hidden · {_displayController.ClusterCount} grouped"; _drawerPanel.TopResults = delegate { List<(string, AtlasId)> list = new List<(string, AtlasId)>(); PinQuery pinQuery = PinQuery.Parse(_displayController.QueryText); foreach (AtlasPin item in _pinStore.Living) { if (!item.Archived && pinQuery.Matches(item)) { list.Add(((item.Name.Length == 0) ? "(unnamed)" : item.Name, item.Id)); if (list.Count >= 6) { break; } } } return list; }; _drawerPanel.ViewNames = delegate { List<string> list = new List<string>(); foreach (SavedView view in _savedViews.Views) { list.Add(view.Name); if (list.Count >= 5) { break; } } return list; }; } private bool ApplySavedView(string name) { if (!_savedViews.TryGet(name, out SavedView view)) { return false; } _settings.DrawerShowDirt.Value = view.ShowDirt; _settings.DrawerShowPaved.Value = view.ShowPaved; _settings.DrawerShowPins.Value = view.ShowPins; _settings.DrawerCluster.Value = view.ClusterEnabled; _renderer.SetOverlayEnabled(RoadKind.Dirt, view.ShowDirt); _renderer.SetOverlayEnabled(RoadKind.Paved, view.ShowPaved); _displayController.ShowPins = view.ShowPins; _displayController.ClusterEnabled = view.ClusterEnabled; _displayController.SetQuery(view.Query); ReapplyDisplay(); return true; } private void ReapplyDisplay() { if (_mapReady) { _displayController.Apply(_pinStore, _pinAdapter); } } private void ResyncPins() { _pinAdapter.SyncAllPins(_pinStore, _displayController.IsDisplayHidden); ReapplyDisplay(); } private void CaptureQuickPin() { if (_quickPinCapture.TryCapture(_pinStore, out string message, out AtlasPin created)) { if (created != null) { _displayController.MarkStickyVisible(created.Id); } ResyncPins(); } if (message.Length > 0) { Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)1, message, 0, (Sprite)null); } } } private bool PaletteActive() { if (_settings.EnhancedPinPalette.Value && !_compatibility.PinManagerPresent) { return !_palettePanel.HasFailed; } return false; } private void OpenSidePanel(int token, CcSidePanel panel) { if (!AtlasAccessAllowed(out string denial)) { Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)1, denial, 0, (Sprite)null); } } else { panel.UiScale = _settings.UiScale.Value; _mapUi.OpenExclusive(token, panel.Toggle); } } private void ArmQuickPin() { if (!AtlasAccessAllowed(out string denial)) { Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)1, denial, 0, (Sprite)null); } return; } try { _mapUi.CloseAllSurfaces(); Minimap instance = Minimap.instance; if (instance != null) { instance.SetMapMode((MapMode)1); } } catch { } _quickPinGate.Arm(Time.frameCount); Player localPlayer2 = Player.m_localPlayer; if (localPlayer2 != null) { ((Character)localPlayer2).Message((MessageType)2, AtlasStrings.Get("quickpin.armed"), 0, (Sprite)null); } } private void ToggleDrawer() { if (AtlasAccessAllowed(out string denial)) { _drawerPanel.UiScale = _settings.UiScale.Value; _drawerPanel.Toggle(_settings.DrawerShowDirt.Value, _settings.DrawerShowPaved.Value, _settings.DrawerShowPins.Value, _settings.DrawerCluster.Value); return; } Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)1, denial, 0, (Sprite)null); } } private void UpdateEditHint(float unscaledDeltaTime) { //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) _hintElapsed += unscaledDeltaTime; if (_hintElapsed < 0.2f) { return; } _hintElapsed = 0f; EnforceVanillaPaletteVisibility(); _mapUi.UpdateLayout(); if (_workbenchPanel.IsVisible) { _mapUi.SetHint(null); _mapUi.SetContext(null, null); return; } PinData pin = null; Vector3 worldPosition; float distance; bool flag = MinimapReflection.TryScreenToWorldPoint(Input.mousePosition, out worldPosition) && _pinAdapter.TryFindNearest(worldPosition, 30f, out pin, out distance); if (flag && _pinAdapter.TryGetManagedId(pin, out var id)) { _contextGrace = 1.5f; _mapUi.SetHint(AtlasStrings.Format("hud.editHint", _settings.WorkbenchHotkey.Value)); AtlasId captured = id; _mapUi.SetContext(AtlasStrings.Get("hud.editPin"), delegate { OpenWorkbenchForId(captured); }); } else if (flag && _pinAdapter.IsAdoptableVanilla(pin) && !_compatibility.PinManagerPresent) { _contextGrace = 1.5f; _mapUi.SetHint(AtlasStrings.Format("hud.editHint", _settings.WorkbenchHotkey.Value)); PinData capturedPin = pin; _mapUi.SetContext(AtlasStrings.Get("hud.upgradeEdit"), delegate { UpgradeAndEdit(capturedPin); }); } else if (!_mapUi.PointerOverContext) { _contextGrace -= 0.2f; if (!(_contextGrace > 0f)) { _mapUi.SetHint(null); _mapUi.SetContext(null, null); } } } private void OpenWorkbenchForId(AtlasId id) { if (_pinCommands == null || !_pinStore.TryGet(id, out AtlasPin pin) || pin.Deleted) { return; } if (!AtlasAccessAllowed(out string denial)) { Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)1, denial, 0, (Sprite)null); } } else { _workbenchPanel.UiScale = _settings.UiScale.Value; _mapUi.OpenExclusive(_workbenchToken, delegate { _workbenchPanel.OpenForManaged(pin, _pinCommands.Operations, ResyncPins); }); } } private void UpgradeAndEdit(PinData pin) { if (_pinCommands == null) { return; } if (!AtlasAccessAllowed(out string denial)) { Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)1, denial, 0, (Sprite)null); } } else { if (!_pinAdapter.ContainsPin(pin) || !_pinAdapter.IsAdoptableVanilla(pin)) { return; } AtlasPin managed = _pinAdapter.Adopt(_pinStore, pin); if (managed != null) { _workbenchPanel.UiScale = _settings.UiScale.Value; _mapUi.OpenExclusive(_workbenchToken, delegate { _workbenchPanel.OpenForManaged(managed, _pinCommands.Operations, ResyncPins); }); } } } private void HandlePaletteBirth(PinData born) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Expected I4, but got Unknown string committedName = born.m_name ?? ""; bool num = _pinAdapter.ContainsPin(born); PinData val = (num ? null : _pinAdapter.TryFindAdoptableAt(born.m_pos, committedName)); PaletteBirthResolution.Action action = PaletteBirthResolution.Decide(num, num && _pinAdapter.IsAdoptableVanilla(born), val != null, committedName); AtlasPin atlasPin; switch (action) { case PaletteBirthResolution.Action.AdoptBorn: atlasPin = _pinAdapter.Adopt(_pinStore, born); break; case PaletteBirthResolution.Action.AdoptReplacement: atlasPin = _pinAdapter.Adopt(_pinStore, val); _log.LogInfo((object)"Palette birth: the naming close replaced the pin object; adopted the replacement at the same spot (RC12 blocker 5)."); break; case PaletteBirthResolution.Action.RecreateManaged: { RoadPoint position = new RoadPoint(born.m_pos.x, born.m_pos.y, born.m_pos.z); int bornType = (int)born.m_type; atlasPin = _pinStore.Create(delegate(AtlasPin pin) { pin.Name = committedName; pin.IconId = IconRegistry.FromVanillaType(bornType); pin.Source = AtlasPinSource.Managed; pin.Position = position; }); _log.LogInfo((object)"Palette birth: the named pin's rendering vanished at naming close; recreated it as a managed marker (RC12 blocker 5)."); break; } case PaletteBirthResolution.Action.DropForeign: _log.LogInfo((object)"Palette birth: the named pin is not adoptable (foreign or already tracked); left untouched."); return; default: if (_settings.DebugLogging.Value) { _log.LogInfo((object)"Palette birth: naming was cancelled; nothing created."); } return; } if (atlasPin == null) { return; } string iconId = _birthTracker.IconId; string category = _birthTracker.Category; _pinStore.Mutate(atlasPin.Id, delegate(AtlasPin pin) { if (iconId.Length > 0) { pin.IconId = iconId; } pin.Category = category; pin.Source = AtlasPinSource.Managed; }); _palettePanel.NoteUsed(iconId); _displayController.MarkStickyVisible(atlasPin.Id); ResyncPins(); if (_settings.DebugLogging.Value) { _log.LogInfo((object)$"Palette marker born managed: {atlasPin.Id} icon {iconId} category \"{category}\"."); } } private void EnforceVanillaPaletteVisibility() { bool flag = !_settings.Enabled.Value || !_settings.EnhancedPinPalette.Value || _settings.ShowVanillaPinPalette.Value || _settings.ShowVanillaMapControls.Value || _compatibility.PinManagerPresent || _palettePanel.HasFailed || _mapUi.HasFailed; foreach (GameObject placeableIconButton in MinimapReflection.GetPlaceableIconButtons()) { if ((Object)(object)placeableIconButton != (Object)null && placeableIconButton.activeSelf != flag) { placeableIconButton.SetActive(flag); } } bool flag2 = !_settings.Enabled.Value || _settings.ShowVanillaMapControls.Value || _compatibility.PinManagerPresent || _systemMarkersPanel.HasFailed || _drawerPanel.HasFailed || _mapUi.HasFailed; foreach (GameObject systemFilterButton in MinimapReflection.GetSystemFilterButtons()) { if ((Object)(object)systemFilterButton != (Object)null && systemFilterButton.activeSelf != flag2) { systemFilterButton.SetActive(flag2); } } GameObject val = null; try { val = (((Object)(object)Minimap.instance != (Object)null && (Object)(object)Minimap.instance.m_publicPosition != (Object)null) ? ((Component)Minimap.instance.m_publicPosition).gameObject : null); if ((Object)(object)val != (Object)null && val.activeSelf != flag2) { val.SetActive(flag2); } } catch { } if (MinimapReflection.TryGetVanillaRailContainers(out GameObject placeablesContainer, out GameObject filtersContainer, out bool sharedContainer, out string diagnostics)) { if (sharedContainer) { SetRailContainerActive(placeablesContainer, flag || flag2); } else { if ((Object)(object)placeablesContainer != (Object)null) { SetRailContainerActive(placeablesContainer, flag); } if ((Object)(object)filtersContainer != (Object)null) { SetRailContainerActive(filtersContainer, flag2); } } } if (!string.Equals(diagnostics, _lastRailDiagnostics, StringComparison.Ordinal)) { _lastRailDiagnostics = diagnostics; _log.LogInfo((object)("Vanilla rail chrome: " + diagnostics + ".")); } if (OrphanChromeRule.MustRestore(flag || flag2)) { _chromeSweep.RestoreAll(); } else { List<GameObject> list = new List<GameObject> { placeablesContainer, filtersContainer, val }; foreach (GameObject placeableIconButton2 in MinimapReflection.GetPlaceableIconButtons()) { list.Add(placeableIconButton2); } foreach (GameObject systemFilterButton2 in MinimapReflection.GetSystemFilterButtons()) { list.Add(systemFilterButton2); } _chromeSweep.Sweep(list); } if (!string.Equals(_chromeSweep.LastDiagnostics, _lastChromeSweepDiagnostics, StringComparison.Ordinal)) { _lastChromeSweepDiagnostics = _chromeSweep.LastDiagnostics; if (_lastChromeSweepDiagnostics.Length > 0) { _log.LogInfo((object)("Vanilla chrome sweep: " + _lastChromeSweepDiagnostics + ".")); } } } private static void SetRailContainerActive(GameObject container, bool visible) { if (container.activeSelf != visible) { container.SetActive(visible); } } private void RestoreVanillaPalette() { try { _chromeSweep.RestoreAll(); if (MinimapReflection.TryGetVanillaRailContainers(out GameObject placeablesContainer, out GameObject filtersContainer, out bool _, out string _)) { if ((Object)(object)placeablesContainer != (Object)null && !placeablesContainer.activeSelf) { placeablesContainer.SetActive(true); } if ((Object)(object)filtersContainer != (Object)null && !filtersContainer.activeSelf) { filtersContainer.SetActive(true); } } foreach (GameObject placeableIconButton in MinimapReflection.GetPlaceableIconButtons()) { if ((Object)(object)placeableIconButton != (Object)null && !placeableIconButton.activeSelf) { placeableIconButton.SetActive(true); } } foreach (GameObject systemFilterButton in MinimapReflection.GetSystemFilterButtons()) { if ((Object)(object)systemFilterButton != (Object)null && !systemFilterButton.activeSelf) { systemFilterButton.SetActive(true); } } if ((Object)(object)Minimap.instance != (Object)null && (Object)(object)Minimap.instance.m_publicPosition != (Object)null && !((Component)Minimap.instance.m_publicPosition).gameObject.activeSelf) { ((Component)Minimap.instance.m_publicPosition).gameObject.SetActive(true); } } catch { } } private void OpenWorkbenchAtCursor() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) if (!MinimapReflection.TryScreenToWorldPoint(Input.mousePosition, out var worldPosition)) { Player localPlayer = Player.m_localPlayer; if (localPlayer == null) { return; } worldPosition = ((Component)localPlayer).transform.position; } OpenWorkbenchNear(worldPosition); } private bool AtlasAccessAllowed(out string denial) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) denial = ""; try { if ((Object)(object)ZoneSystem.instance == (Object)null || !ZoneSystem.instance.GetGlobalKey("nomap")) { return true; } Player localPlayer = Player.m_localPlayer; if (localPlayer != null && SurveyScanner.AnyInstanceNear("piece_maptable", ((Component)localPlayer).transform.position, 10f)) { return true; } denial = AtlasStrings.Get("hud.noMapNeedTable"); return false; } catch { return true; } } private void ShowOnboardingOnce() { if (_onboardingChecked) { return; } _onboardingChecked = true; try { string path = Path.Combine(Paths.ConfigPath, "ConcernedCatMods", "ConcernedCartographer", "onboarding-shown.txt"); if (!File.Exists(path)) { Directory.CreateDirectory(Path.GetDirectoryName(path)); File.WriteAllText(path, DateTime.UtcNow.ToString("o")); Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)2, AtlasStrings.Get("hud.onboarding"), 0, (Sprite)null); } } } catch { } } private static bool GamepadDown(string buttonName) { if (string.IsNullOrEmpty(buttonName)) { return false; } try { return ZInput.GetButtonDown(buttonName); } catch { return false; } } private void OpenWorkbenchNear(Vector3 world) { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_01fb: Unknown result type (might be due to invalid IL or missing references) if (_pinCommands == null) { return; } if (!AtlasAccessAllowed(out string denial)) { Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)1, denial, 0, (Sprite)null); } return; } _workbenchPanel.UiScale = _settings.UiScale.Value; RoadPoint other = new RoadPoint(world.x, world.y, world.z); PinOperations operations = _pinCommands.Operations; Action resync = ResyncPins; AtlasPin atlasPin = null; float num = 30f; foreach (AtlasPin item in _pinStore.Living) { float num2 = item.Position.HorizontalDistanceTo(in other); if (num2 < num) { num = num2; atlasPin = item; } } if (atlasPin != null) { AtlasPin captured = atlasPin; _mapUi.OpenExclusive(_workbenchToken, delegate { _workbenchPanel.OpenForManaged(captured, operations, resync); }); } else { if (!_pinAdapter.TryFindNearest(world, 30f, out PinData pin, out float _)) { return; } if (_pinAdapter.IsAdoptableVanilla(pin) && _compatibility.PinManagerPresent) { _workbenchPanel.OpenReadOnly("\"" + pin.m_name + "\" — another pin manager is installed; use 'cc_pins adopt' to manage this pin here"); } else if (_pinAdapter.IsAdoptableVanilla(pin)) { PinData captured2 = pin; _workbenchPanel.OpenAdoptPrompt(captured2.m_name ?? "", () => _pinAdapter.Adopt(_pinStore, captured2), operations, resync); } else { _workbenchPanel.OpenReadOnly($"\"{pin.m_name}\" ({pin.m_type})"); } } } public void SaveAll() { _drawerPanel.FlushPosition(); SaveIfDirty(); SavePinsSnapshot(); _savedViewPersistence.Save(_savedViews); } internal string ExecuteAtlasCommand(string[] args) { if (!AtlasAccessAllowed(out string denial)) { return denial; } if (_disposed || !_mapReady) { return "Concerned Cartographer: no world is loaded yet."; } string text = ((args.Length == 0) ? "status" : args[0].ToLowerInvariant()); string text2 = ((args.Length > 1) ? string.Join(" ", args, 1, args.Length - 1) : ""); switch (text) { case "status": return "Atlas view: query \"" + _displayController.QueryText + "\", pins " + (_displayController.ShowPins ? "on" : "off") + ", cluster " + (_displayController.ClusterEnabled ? "on" : "off") + ", dirt " + (_settings.DrawerShowDirt.Value ? "on" : "off") + ", paved " + (_settings.DrawerShowPaved.Value ? "on" : "off") + ". " + $"{_displayController.VisibleCount} shown, {_displayController.HiddenByFilter} filtered, {_displayController.ClusterCount} clusters."; case "query": _displayController.SetQuery(text2); ReapplyDisplay(); return $"Filter applied: \"{text2}\" — {_displayController.VisibleCount} shown, {_displayController.HiddenByFilter} filtered. Filters are display-only; 'cc_atlas clear' restores everything."; case "clear": _displayController.SetQuery(""); ReapplyDisplay(); return "Filter cleared; all pins shown."; case "paved": case "dirt": case "pins": case "cluster": { if (!TryParseOnOff(text2, out var enabled)) { return "Usage: cc_atlas " + text + " on|off"; } ApplyToggle(text, enabled); return text + " " + (enabled ? "on" : "off") + "."; } case "view": return HandleViewCommand(text2); case "compat": return _compatibility.Report(); case "backup": { long? worldUid = _worldUid; if (worldUid.HasValue) { long valueOrDefault = worldUid.GetValueOrDefault(); return "Backed up to " + _backupTools.Backup(valueOrDefault); } return "No world loaded."; } case "backups": { long? worldUid = _worldUid; if (worldUid.HasValue) { long valueOrDefault3 = worldUid.GetValueOrDefault(); List<string> list = _backupTools.ListBackups(valueOrDefault3); if (list.Count == 0) { return "No backups yet. 'cc_atlas backup' creates one; exports/imports use the same folders."; } StringBuilder stringBuilder2 = new StringBuilder($"{list.Count} backup(s), newest first:"); for (int i = 0; i < list.Count && i < 10; i++) { stringBuilder2.Append($"\n {i + 1}. {Path.GetFileName(list[i])}"); } stringBuilder2.Append("\n'cc_atlas restore <n>' restores one (takes a safety backup first)."); return stringBuilder2.ToString(); } return "No world loaded."; } case "restore": { long? worldUid = _worldUid; if (worldUid.HasValue) { long valueOrDefault4 = worldUid.GetValueOrDefault(); List<string> list2 = _backupTools.ListBackups(valueOrDefault4); if (!int.TryParse(text2.Trim(), out var result) || result < 1 || result > list2.Count) { return "Usage: cc_atlas restore <n> (see 'cc_atlas backups')"; } return _backupTools.Restore(valueOrDefault4, list2[result - 1]); } return "No world loaded."; } case "support": { long? worldUid = _worldUid; if (worldUid.HasValue) { long valueOrDefault2 = worldUid.GetValueOrDefault(); string text3 = _backupTools.WriteSupportReport(valueOrDefault2, "0.10.0", $"enabled={_settings.Enabled.Value}, capture={_settings.CaptureConstructionActions.Value}, " + $"reconcile={_settings.ReconcileTerrainChanges.Value}, " + $"survey={_settings.SurveyRulesEnabled.Value}, cluster={_settings.DrawerCluster.Value}, " + $"contrast={_settings.HighContrast.Value}, uiScale={_settings.UiScale.Value}"); return "Sanitized support report (no positions/names/notes/world ids/paths) written to " + text3; } return "No world loaded."; } case "views": { StringBuilder stringBuilder = new StringBuilder("Saved views:"); if (_savedViews.Views.Count == 0) { return "Saved views: none. 'cc_atlas view save <name>' captures the current filter/layer state."; } foreach (SavedView view in _savedViews.Views) { stringBuilder.Append("\n \"" + view.Name + "\" — query \"" + view.Query + "\""); } return stringBuilder.ToString(); } default: return "Usage: cc_atlas [status|query <text>|clear|pins on/off|cluster on/off|dirt on/off|paved on/off|view save/apply/del <name>|views]"; } } internal string ExecuteSurveyCommand(string[] args) { if (!AtlasAccessAllowed(out string denial)) { return denial; } if (_disposed || !_mapReady) { return "Concerned Cartographer: no world is loaded yet."; } string text = ((args.Length == 0) ? "status" : args[0].ToLowerInvariant()); string text2 = ((args.Length > 1) ? args[1].ToLowerInvariant() : ""); string text3 = ((args.Length > 1) ? args[1] : ""); IReadOnlyList<SurveyEngine.Observation> observations = _surveyEngine.Observations; switch (text) { case "status": return "Survey: " + (_settings.SurveyRulesEnabled.Value ? "ENABLED" : "disabled (Survey/SurveyRulesEnabled)") + ", " + $"{_surveyEngine.Rules.Rules.Count} rule(s), {_surveyEngine.Rules.Blacklist.Count} blacklist pattern(s), " + $"{observations.Count} pending observation(s). Rules file: {SurveyRulePersistence.RulePath}"; case "list": { if (observations.Count == 0) { return "No pending observations."; } StringBuilder stringBuilder = new StringBuilder($"{observations.Count} observation(s):"); for (int i = 0; i < observations.Count && i < 15; i++) { SurveyEngine.Observation observation = observations[i]; stringBuilder.Append($"\n {i + 1}. {observation.SuggestedName} [{observation.Category}] at ({observation.Position.X:0}, {observation.Position.Z:0})"); } if (observations.Count > 15) { stringBuilder.Append($"\n ... and {observations.Count - 15} more."); } stringBuilder.Append("\ncc_survey accept <n|all> / reject <n|all>"); return stringBuilder.ToString(); } case "accept": { if (text2 == "all") { int num3 = _surveyEngine.AcceptAll(_pinStore, delegate(AtlasPin atlasPin) { _displayController.MarkStickyVisible(atlasPin.Id); }); ResyncPins(); return $"Accepted {num3} observation(s) as markers."; } Guid? guid = null; int result3; if (text3.StartsWith("id:", StringComparison.OrdinalIgnoreCase) && Guid.TryParse(text3.Substring(3), out var result2)) { guid = result2; } else if (int.TryParse(text2, out result3) && result3 >= 1 && result3 <= observations.Count) { guid = observations[result3 - 1].Id; } if (guid.HasValue) { Guid valueOrDefault = guid.GetValueOrDefault(); if (!_surveyEngine.Accept(valueOrDefault, _pinStore, out AtlasPin created)) { return "That observation is no longer pending — the list just updated."; } if (created != null) { _displayController.MarkStickyVisible(created.Id); } ResyncPins(); return "Accepted \"" + created?.Name + "\" as a marker."; } return "Usage: cc_survey accept <n|all>"; } case "reject": { if (text2 == "all") { int num6 = _surveyEngine.RejectAll(DateTime.UtcNow); SaveRejectedIfDirty(); return $"Rejected {num6} observation(s); they moved to the Rejected list."; } Guid? guid2 = null; int result7; if (text3.StartsWith("id:", StringComparison.OrdinalIgnoreCase) && Guid.TryParse(text3.Substring(3), out var result6)) { guid2 = result6; } else if (int.TryParse(text2, out result7) && result7 >= 1 && result7 <= observations.Count) { guid2 = observations[result7 - 1].Id; } if (guid2.HasValue) { Guid valueOrDefault2 = guid2.GetValueOrDefault(); if (!_surveyEngine.Reject(valueOrDefault2, DateTime.UtcNow)) { return "That observation is no longer pending — the list just updated."; } SaveRejectedIfDirty(); return "Rejected; it moved to the Rejected list."; } return "Usage: cc_survey reject <n|all>"; } case "rejected": { if (_surveyEngine.Rejected.Count == 0) { return "The Rejected list is empty."; } StringBuilder stringBuilder2 = new StringBuilder($"{_surveyEngine.Rejected.Count} rejected:"); for (int num4 = 0; num4 < _surveyEngine.Rejected.Count && num4 < 15; num4++) { SurveyEngine.RejectedObservation rejectedObservation = _surveyEngine.Rejected[num4]; stringBuilder2.Append($"\n {num4 + 1}. {rejectedObservation.SuggestedName} [{rejectedObservation.Category}] at ({rejectedObservation.Position.X:0}, {rejectedObservation.Position.Z:0})"); } if (_surveyEngine.Rejected.Count > 15) { stringBuilder2.Append($"\n ... and {_surveyEngine.Rejected.Count - 15} more."); } return stringBuilder2.ToString(); } case "restore": { if (text2 == "all") { int num = _surveyEngine.RestoreAllRejected(DateTime.UtcNow); SaveRejectedIfDirty(); return $"Restored {num} rejected observation(s) to pending review."; } int num2 = -1; int result; if (text3.StartsWith("key:", StringComparison.OrdinalIgnoreCase)) { num2 = _surveyEngine.FindRejectedIndex(text3.Substring(4)); if (num2 < 0) { return "That rejected entry is no longer listed — the list just updated."; } } else if (int.TryParse(text2, out result)) { num2 = result - 1; } if (num2 >= 0 && _surveyEngine.RestoreRejected(num2, DateTime.UtcNow)) { SaveRejectedIfDirty(); return "Restored the rejected entry to pending review."; } return "Usage: cc_survey restore <n|all>"; } case "acceptrejected": { int num5 = -1; int result5; if (text3.StartsWith("key:", StringComparison.OrdinalIgnoreCase)) { num5 = _surveyEngine.FindRejectedIndex(text3.Substring(4)); if (num5 < 0) { return "That rejected entry is no longer listed — the list just updated."; } } else if (int.TryParse(text2, out result5)) { num5 = result5 - 1; } if (num5 >= 0 && _surveyEngine.AcceptRejected(num5, _pinStore, out AtlasPin created2)) { if (created2 != null) { _displayController.MarkStickyVisible(created2.Id); } ResyncPins(); SaveRejectedIfDirty(); return "Accepted \"" + created2?.Name + "\" as a marker."; } return "Usage: cc_survey acceptrejected <n>"; } case "rules": { if (_surveyEngine.Rules.Rules.Count == 0) { return "No survey rules. Add one from the Survey panel's Rules view."; } StringBuilder stringBuilder3 = new StringBuilder($"{_surveyEngine.Rules.Rules.Count} rule(s):"); for (int num7 = 0; num7 < _surveyEngine.Rules.Rules.Count; num7++) { SurveyRule surveyRule2 = _surveyEngine.Rules.Rules[num7]; stringBuilder3.Append(string.Format("\n {0}. [{1}] {2} → {3} ({4})", num7 + 1, surveyRule2.Enabled ? "on " : "OFF", surveyRule2.Pattern, surveyRule2.Category, surveyRule2.IconId)); } return stringBuilder3.ToString(); } case "ruleon": case "ruleoff": { if (int.TryParse(text2, out var result4)) { SurveyRule surveyRule = _surveyEngine.Rules.SetRuleEnabled(result4 - 1, text == "ruleon"); if (surveyRule != null) { _surveyRulePersistence.Save(_surveyEngine.Rules); return "Rule \"" + surveyRule.Pattern + "\" is now " + (surveyRule.Enabled ? "enabled" : "disabled") + "."; } } return "Usage: cc_survey ruleon <n> / ruleoff <n>"; } case "ruledel": { if (int.TryParse(text2, out var result8)) { SurveyRule surveyRule3 = _surveyEngine.Rules.RemoveRuleAt(result8 - 1); if (surveyRule3 != null) { _surveyRulePersistence.Save(_surveyEngine.Rules); return "Removed rule \"" + surveyRule3.Pattern + "\"."; } } return "Usage: cc_survey ruledel <n>"; } case "ruleadd": { string text4 = SurveyRuleSet.Clean(text2); if (text4.Length == 0 || text4 == "*") { return "Usage: cc_survey ruleadd <prefab-pattern> ('bush*' matches prefixes)"; } string text5 = ((args.Length > 2) ? args[2] : "cc:resource"); string text6 = ((args.Length > 3) ? string.Join(" ", args, 3, args.Length - 3) : "Resources"); _surveyEngine.Rules.AddRule(new SurveyRule(text4, text5, text6, 30f, 120f)); _surveyRulePersistence.Save(_surveyEngine.Rules); return "Added rule \"" + text4 + "\" → " + text6 + " (" + text5 + ")."; } case "reload": _surveyEngine.Rules = _surveyRulePersistence.LoadOrCreate(); return $"Reloaded {_surveyEngine.Rules.Rules.Count} rule(s) and {_surveyEngine.Rules.Blacklist.Count} blacklist pattern(s)."; case "path": return SurveyRulePersistence.RulePath + " (the file is the shareable import/export format)"; default: return "Usage: cc_survey [status|list|accept <n|all>|reject <n|all>|rejected|restore <n|all>|acceptrejected <n>|rules|ruleon/ruleoff/ruledel <n>|ruleadd <pattern> [icon] [category]|reload|path]"; } } private void SaveRejectedIfDirty() { if (!_surveyEngine.RejectedDirty) { return; } long? worldUid = _worldUid; if (worldUid.HasValue) { long valueOrDefault = worldUid.GetValueOrDefault(); if (_surveyRejectedPersistence.Save(valueOrDefault, _surveyEngine.Rejected)) { _surveyEngine.MarkRejectedClean(); } } } private string HandleViewCommand(string remainder) { int num = remainder.IndexOf(' '); string text = ((num < 0) ? remainder : remainder.Substring(0, num)).ToLowerInvariant(); string text2 = ((num < 0) ? "" : remainder.Substring(num + 1).Trim()); if (text2.Length == 0) { return "Usage: cc_atlas view save|apply|del <name>"; } switch (text) { case "save": _drawerPanel.ViewSaved?.Invoke(text2); return "View \"" + text2 + "\" saved with the current filter and layer state."; case "apply": if (!ApplySavedView(text2)) { return "No view named \"" + text2 + "\"."; } return "View \"" + text2 + "\" applied."; case "del": { bool num2 = _savedViews.Remove(text2); _savedViewPersistence.Save(_savedViews); if (!num2) { return "No view named \"" + text2 + "\"."; } return "View \"" + text2 + "\" deleted."; } default: return "Usage: cc_atlas view save|apply|del <name>"; } } private void ApplyToggle(string which, bool enabled) { switch (which) { case "pins": _settings.DrawerShowPins.Value = enabled; _displayController.ShowPins = enabled; ReapplyDisplay(); break; case "cluster": _settings.DrawerCluster.Value = enabled; _displayController.ClusterEnabled = enabled; ReapplyDisplay(); break; case "dirt": _settings.DrawerShowDirt.Value = enabled; _renderer.SetOverlayEnabled(RoadKind.Dirt, enabled); break; case "paved": _settings.DrawerShowPaved.Value = enabled; _renderer.SetOverlayEnabled(RoadKind.Paved, enabled); break; } } private static bool TryParseOnOff(string text, out bool enabled) { switch (text.Trim().ToLowerInvariant()) { case "on": case "true": case "1": enabled = true; return true; case "off": case "false": case "0": enabled = false; return true; default: enabled = false; return false; } } private void SavePinsSnapshot() { long? worldUid = _worldUid; if (worldUid.HasValue) { long valueOrDefault = worldUid.GetValueOrDefault(); _pinPersistence.Save(valueOrDefault, _pinStore); _routePersistence.Save(valueOrDefault, _routeStore); } } internal string ExecuteSyncCommand(string[] args) { if (!AtlasAccessAllowed(out string denial)) { return denial; } if (_disposed || !_mapReady) { return "Concerned Cartographer: no world is loaded yet."; } string text = ((args.Length == 0) ? "status" : args[0].ToLowerInvariant()); string text2 = ((args.Length > 1) ? string.Join(" ", args, 1, args.Length - 1).Trim() : ""); switch (text) { case "status": var (list3, list4) = SyncPlanner.CollectShared(_pinStore, _routeStore); return $"Sync: sharing {list3.Count} pin(s) and {list4.Count} route(s) " + $"(scope table/server, tombstones included). Inbox: {_syncInbox.Envelopes.Count} pending share(s). " + "Set a pin/route scope with 'cc_pins scope table' or 'cc_routes ...' to share it; 'cc_sync share' broadcasts."; case "share": { var (list, list2) = SyncPlanner.CollectShared(_pinStore, _routeStore); if (list.Count == 0 && list2.Count == 0) { return "Nothing is scoped for sharing yet. 'cc_pins scope table' near a pin shares it."; } Player localPlayer = Player.m_localPlayer; string authorName = ((localPlayer != null) ? localPlayer.GetPlayerName() : null) ?? ""; _syncTransport.Share(_authorId, authorName, list, list2, out string message); _log.LogInfo((object)("Sync share: " + message)); return message; } case "inbox": { if (_syncInbox.Envelopes.Count == 0) { return "Sync inbox: empty."; } StringBuilder stringBuilder = new StringBuilder("Sync inbox:"); foreach (SyncInbox.Envelope envelope3 in _syncInbox.Envelopes) { stringBuilder.Append($"\n {envelope3.AuthorName}: {envelope3.Pins.Count} pin(s), {envelope3.Routes.Count} route(s) " + $"at {envelope3.ReceivedUtc:HH:mm} UTC — 'cc_sync preview {envelope3.AuthorName}'"); } return stringBuilder.ToString(); } case "preview": { if (!_syncInbox.TryPeek(text2, out SyncInbox.Envelope envelope2)) { return "No pending share from \"" + text2 + "\". 'cc_sync inbox' lists them."; } SyncPlan syncPlan2 = SyncPlanner.Plan(_pinStore, _routeStore, envelope2.Pins, envelope2.Routes); List<string> list5 = syncPlan2.DeletionNames(10); string text4 = ((list5.Count == 0) ? "" : ("\n Would DELETE: " + string.Join(", ", list5) + ((syncPlan2.TombstonePins.Count + syncPlan2.TombstoneRoutes.Count > list5.Count) ? $" (+{syncPlan2.TombstonePins.Count + syncPlan2.TombstoneRoutes.Count - list5.Count} more)" : ""))); return "Share from " + envelope2.AuthorName + ": " + syncPlan2.Summary() + "." + text4 + ((syncPlan2.PinConflicts.Count + syncPlan2.RouteConflicts.Count > 0) ? (" Apply with 'cc_sync apply " + envelope2.AuthorName + " mine' (keep local on conflicts) or '... theirs'.") : (" Apply with 'cc_sync apply " + envelope2.AuthorName + "'.")); } case "apply": { string[] array = text2.Split(new char[1] { ' ' }); bool flag = array.Length > 1 && string.Equals(array[^1], "theirs", StringComparison.OrdinalIgnoreCase); string text3 = ((flag || (array.Length > 1 && string.Equals(array[^1], "mine", StringComparison.OrdinalIgnoreCase))) ? string.Join(" ", array, 0, array.Length - 1) : text2); if (!_syncInbox.TryTake(text3, out SyncInbox.Envelope envelope)) { return "No pending share from \"" + text3 + "\"."; } SyncPlan syncPlan = SyncPlanner.Plan(_pinStore, _routeStore, envelope.Pins, envelope.Routes); int num = SyncPlanner.Apply(syncPlan, _pinStore, _routeStore, flag); ResyncPins(); _routeRedrawPending = true; SavePinsSnapshot(); _log.LogInfo((object)$"Sync apply: {num} change(s); {syncPlan.Summary()}"); return $"Applied {num} change(s) from {envelope.AuthorName} " + "(" + (flag ? "conflicts took their side" : "conflicts kept your side") + "). " + syncPlan.Summary(); } case "clear": _syncInbox.Clear(); return "Sync inbox cleared."; default: return "Usage: cc_sync [status|share|inbox|preview <author>|apply <author> [mine|theirs]|clear]"; } } internal string ExecuteRouteCommand(string[] args) { //IL_0046: Unknown result type (might be due to invalid IL or missing references) if (!AtlasAccessAllowed(out string denial)) { return denial; } if (_disposed || !_mapReady || _routeCommands == null) { return "Concerned Cartographer: no world is loaded yet."; } Player localPlayer = Player.m_localPlayer; if (localPlayer == null) { return "Concerned Cartographer: no local player."; } return _routeCommands.Execute(args, ((Component)localPlayer).transform.position); } private void HandleTerrainOperation(CapturedTerrainOperation operation) { //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_0292: Unknown result type (might be due to invalid IL or missing references) if (_disposed || !_settings.Enabled.Value || !_mapReady || _pipeline == null) { return; } long? worldUid = _worldUid; if (!worldUid.HasValue) { return; } _rateLimited.Info("terrain-action-" + operation.Category, $"Terrain action classified: {operation.ActionDescription} r={operation.RadiusMeters:0.#}m."); RoadPoint center = new RoadPoint(operation.Position.x, operation.Position.y, operation.Position.z); float radiusMeters = operation.RadiusMeters + 1f; if (!operation.RoadKind.HasValue) { int num = _terrainIntent.AddExclusion(center.X, center.Z, radiusMeters); if (num > 0 && _settings.DebugLogging.Value) { _rateLimited.Info("terrain-intent-add", $"Terraforming r={operation.RadiusMeters:0.#}m: " + $"{num} cell(s) marked not-road ({_terrainIntent.Count} total)."); } } else { _terrainIntent.ClearExclusion(center.X, center.Z, radiusMeters); } RoadKind? roadKind; if (_settings.ReconcileTerrainChanges.Value) { int num2 = 0; roadKind = operation.RoadKind; if (roadKind.HasValue) { RoadKind valueOrDefault = roadKind.GetValueOrDefault(); RoadKind kind = ((valueOrDefault != RoadKind.Dirt) ? RoadKind.Dirt : RoadKind.Paved); num2 = RemoveCoverageWithBackup(kind, center, operation.RadiusMeters); } else { num2 = RemoveCoverageWithBackup(RoadKind.Dirt, center, operation.RadiusMeters) + RemoveCoverageWithBackup(RoadKind.Paved, center, operation.RadiusMeters); } if (num2 > 0) { _redrawPending = true; _log.LogInfo((object)("Reconciled a terrain change (" + operation.ActionDescription + ") " + $"r={operation.RadiusMeters:0.#}m: removed {num2} road point(s).")); } } roadKind = operation.RoadKind; if (roadKind.HasValue) { RoadKind valueOrDefault2 = roadKind.GetValueOrDefault(); if (_settings.CaptureConstructionActions.Value) { ObserveAndDraw(rules: new RoadSamplingRules(_settings.MinimumPointSpacingMeters.Value, _settings.MaximumStrokeGapMeters.Value, _settings.DuplicateSuppressionMeters.Value), source: RoadObservationSource.Construction, kind: valueOrDefault2, position: operation.Position, debugKey: "construction-observed"); } } } private int RemoveCoverageWithBackup(RoadKind kind, RoadPoint center, float radiusMeters) { _persistence.BackupBeforeReconciliation(_worldUid.Value); return _atlas.RemoveCoverage(kind, center, radiusMeters); } private void ObserveAndDraw(RoadObservationSource source, RoadKind kind, Vector3 position, RoadSamplingRules rules, string debugKey) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) if (!_disposed && _settings.Enabled.Value && _mapReady && _pipeline != null) { RoadObservation observation = new RoadObservation(source, kind, new RoadPoint(position.x, position.y, position.z)); int pointCount = _atlas.PointCount; if (_pipeline.Observe(in observation, rules, out var segment)) { _renderer.DrawSegment(segment); } else if (_atlas.PointCount > pointCount) { _renderer.DrawPoint(kind, observation.Position); } if (_settings.DebugLogging.Value) { _rateLimited.Info(debugKey, $"Observed {observation.Source}/{observation.Kind}."); } } } internal string ExecuteRoadCommand(string[] args) { //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_054f: Unknown result type (might be due to invalid IL or missing references) //IL_04c6: Unknown result type (might be due to invalid IL or missing references) //IL_04ec: Unknown result type (might be due to invalid IL or missing references) if (!AtlasAccessAllowed(out string denial)) { return denial; } if (!_disposed && _mapReady && _editor != null) { long? worldUid = _worldUid; if (worldUid.HasValue) { Player localPlayer = Player.m_localPlayer; if (localPlayer == null) { return "Concerned Cartographer: no local player."; } Vector3 position = ((Component)localPlayer).transform.position; RoadPoint position2 = new RoadPoint(position.x, position.y, position.z); string text = ((args.Length == 0) ? "status" : args[0].ToLowerInvariant()); float radius = 10f; if (args.Length > 1 && float.TryParse(args[1], NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) { radius = Mathf.Clamp(result, 1f, 100f); } bool flag; string summary; switch (text) { case "status": { int num3 = 0; foreach (RoadStroke stroke in _atlas.Strokes) { if (stroke.Hidden) { num3++; } } return $"Atlas: {_atlas.Strokes.Count} road(s), {_atlas.PointCount} point(s), " + $"{num3} hidden, undo depth {_editor.UndoCount}. {_editor.DescribeNearest(position2, radius)}"; } case "delete": flag = MutateWithBackup(() => _editor.DeleteNearest(position2, radius, out _lastToolSummary)); summary = _lastToolSummary; break; case "kind": flag = MutateWithBackup(() => _editor.ReclassifyNearest(position2, radius, out _lastToolSummary)); summary = _lastToolSummary; break; case "hide": flag = MutateWithBackup(() => _editor.SetHiddenNearest(position2, radius, hidden: true, out _lastToolSummary)); summary = _lastToolSummary; break; case "unhide": flag = MutateWithBackup(() => _editor.SetHiddenNearest(position2, radius, hidden: false, out _lastToolSummary)); summary = _lastToolSummary; break; case "split": flag = MutateWithBackup(() => _editor.SplitNearest(position2, radius, out _lastToolSummary)); summary = _lastToolSummary; break; case "join": flag = MutateWithBackup(() => _editor.JoinNearest(position2, radius, out _lastToolSummary)); summary = _lastToolSummary; break; case "rebuild": { float num = ((args.Length > 1) ? radius : 32f); _persistence.BackupBeforeReconciliation(_worldUid.Value); int num2 = _atlas.RemoveCoverage(RoadKind.Dirt, position2, num) + _atlas.RemoveCoverage(RoadKind.Paved, position2, num); flag = num2 > 0; summary = $"Cleared {num2} road point(s) within {num:0.#} m. " + "Roads return only when you Pathen/Pave the ground again ('cc_roads undo' reverts)."; break; } case "undo": flag = _editor.Undo(out summary); break; case "align": if (args.Length > 1 && string.Equals(args[1], "clear", StringComparison.OrdinalIgnoreCase)) { _renderer.ClearAlignmentProbe(); _renderer.RedrawAll(_atlas); _redrawPending = false; return "Alignment markers removed."; } if (args.Length > 1 && string.Equals(args[1], "live", StringComparison.OrdinalIgnoreCase)) { RoadKind kind; bool standingOnRoad = _probe.TryClassify(position, out kind); RoadPoint nearest; float distanceMeters; bool hasNearest = _atlas.TryGetNearestPointOnRoads(position2, 50f, out nearest, out distanceMeters); string result2 = LiveAlignmentProbe.BuildReport(position, standingOnRoad, kind, _surveyor?.LatestSample, _pipeline?.LastAccepted, hasNearest, nearest, distanceMeters, _renderer); _log.LogInfo((object)"cc_roads align live: diagnostic report written to the console (positions are never logged)."); return result2; } return _renderer.RunAlignmentProbe(position, _atlas); default: return "Usage: cc_roads [status|delete|kind|hide|unhide|split|join|rebuild|undo] [radius]."; } if (flag) { _redrawPending = true; SaveIfDirty(); _log.LogInfo((object)("Road tool '" + text + "': " + summary)); } return summary; } } return "Concerned Cartographer: no world is loaded yet."; } private bool MutateWithBackup(Func<bool> operation) { _persistence.BackupBeforeReconciliation(_worldUid.Value); return operation(); } public void SaveIfDirty() { long? worldUid = _worldUid; if (worldUid.HasValue) { if (_atlas.IsDirty && _persistence.Save(_worldUid.Value, _atlas)) { _atlas.MarkClean(); } if (_terrainIntent.IsDirty && _terrainIntentPersistence.Save(_worldUid.Value, _terrainIntent)) { _terrainIntent.MarkClean(); } } } public void Dispose() { if (!_disposed) { _workbenchPanel.Close(); RestoreVanillaPalette(); _overlayRelabel.Restore(); _textFocusBlock.Release(); _quickPinGate.Disarm(); MapInputGate.Uninstall(); PlayerInputGate.Uninstall(); PinDeletionWatch.Uninstall(); MapPointerGuard.Clear(); SaveIfDirty(); SavePinsSnapshot(); SaveRejectedIfDirty(); _pipeline?.EndAllStrokes(); _constructionCapture.OperationCaptured -= HandleTerrainOperation; _constructionCapture.Dispose(); _disposed = true; } } private void SwitchWorld(long uid) { if (_worldUid != uid || _surveyor == null) { SaveRejectedIfDirty(); SaveIfDirty(); SavePinsSnapshot(); _worldUid = uid; _atlas = _persistence.Load(uid); _terrainIntent = _terrainIntentPersistence.Load(uid); _pinStore = _pinPersistence.Load(uid); _surveyEngine.ResetSession(); _surveyEngine.LoadRejected(_surveyRejectedPersistence.Load(uid)); _pinStore.LocalAuthor = _authorId; _pinStore.Changed += _pinPersistence.QueueJournal; _pinAdapter.Reset(); _pinCommands = new PinCommandHandler(_pinStore, new PinOperations(_pinStore), _pinAdapter, _log, ResyncPins); _displayController.Reset(); _routeStore = _routePersistence.Load(uid); _routeStore.LocalAuthor = _authorId; _routeStore.Changed += _routePersistence.QueueJournal; _syncInbox.Clear(); _routeCommands = new RouteCommandHandler(_routeStore, new RouteOperations(_routeStore), _atlas, _settings, _log, delegate { _routeRedrawPending = true; }); _pipeline = new RoadObservationPipeline(_atlas, _terrainIntent); _editor = new RoadAtlasEditor(_atlas); _surveyor = new RoadSurveyor(_settings, _probe, _atlas, _log); _redrawPending = false; _autosaveElapsed = 0f; } } } internal sealed class CartographerSettings { public ConfigEntry<bool> Enabled { get; } public ConfigEntry<bool> CaptureConstructionActions { get; } public ConfigEntry<bool> ReconcileTerrainChanges { get; } public ConfigEntry<float> SampleIntervalSeconds { get; } public ConfigEntry<float> MinimumPointSpacingMeters { get; } public ConfigEntry<float> MaximumStrokeGapMeters { get; } public ConfigEntry<float> DuplicateSuppressionMeters { get; } public ConfigEntry<float> AutosaveIntervalSeconds { get; } public ConfigEntry<float> PaintThreshold { get; } public ConfigEntry<int> PaintSampleRadius { get; } public ConfigEntry<int> LineWidthPixels { get; } public ConfigEntry<bool> DebugLogging { get; } public ConfigEntry<bool> DrawCalibrationMarkers { get; } public ConfigEntry<KeyCode> WorkbenchHotkey { get; } public ConfigEntry<KeyCode> DrawerHotkey { get; } public ConfigEntry<bool> DrawerShowDirt { get; } public ConfigEntry<bool> DrawerShowPaved { get; } public ConfigEntry<bool> DrawerShowPins { get; } public ConfigEntry<bool> DrawerCluster { get; } public ConfigEntry<string> DrawerPanelPosition { get; } public ConfigEntry<KeyCode> QuickPinHotkey { get; } public ConfigEntry<float> QuickPinDuplicateRadius { get; } public ConfigEntry<bool> SurveyRulesEnabled { get; } public ConfigEntry<float> SurveyScanIntervalSeconds { get; } public ConfigEntry<float> SurveyScanRadius { get; } public ConfigEntry<float> SurveyBaseExclusionRadius { get; } public ConfigEntry<int> SurveyMaxObservations { get; } public ConfigEntry<KeyCode> RouteDrawModifier { get; } public ConfigEntry<float> RouteEraseRadius { get; } public ConfigEntry<float> RouteSnapRadius { get; } public ConfigEntry<float> RouteOnRoadTolerance { get; } public ConfigEntry<float> RouteOffRoadSpeed { get; } public ConfigEntry<float> RouteOnRoadSpeed { get; } public ConfigEntry<float> UiScale { get; } public ConfigEntry<bool> HighContrast { get; } public ConfigEntry<string> WorkbenchGamepadButton { get; } public ConfigEntry<string> DrawerGamepadButton { get; } public ConfigEntry<bool> EnhancedPinPalette { get; } public ConfigEntry<bool> ShowVanillaPinPalette { get; } public ConfigEntry<CrashConsentState> CrashReportingConsent { get; } public ConfigEntry<int> AcceptedPrivacyPolicyVersion { get; } public ConfigEntry<string> SentryDsn { get; } public ConfigEntry<bool> ShowVanillaMapControls { get; } public ConfigEntry<bool> HighPrecisionLargeMapRoads { get; } private CartographerSettings(ConfigEntry<bool> enabled, ConfigEntry<bool> captureConstructionActions, ConfigEntry<bool> reconcileTerrainChanges, ConfigEntry<float> sampleIntervalSeconds, ConfigEntry<float> minimumPointSpacingMeters, ConfigEntry<float> maximumStrokeGapMeters, ConfigEntry<float> duplicateSuppressionMeters, ConfigEntry<float> autosaveIntervalSeconds, ConfigEntry<float> paintThreshold, ConfigEntry<int> paintSampleRadius, ConfigEntry<int> lineWidthPixels, ConfigEntry<bool> debugLogging, ConfigEntry<bool> drawCalibrationMarkers, ConfigEntry<KeyCode> workbenchHotkey, ConfigEntry<KeyCode> drawerHotkey, ConfigEntry<bool> drawerShowDirt, ConfigEntry<bool> drawerShowPaved, ConfigEntry<bool> drawerShowPins, ConfigEntry<bool> drawerCluster, ConfigEntry<string> drawerPanelPosition, ConfigEntry<KeyCode> quickPinHotkey, ConfigEntry<float> quickPinDuplicateRadius, ConfigEntry<bool> surveyRulesEnabled, ConfigEntry<float> surveyScanIntervalSeconds, ConfigEntry<float> surveyScanRadius, ConfigEntry<float> surveyBaseExclusionRadius, ConfigEntry<int> surveyMaxObservations, ConfigEntry<KeyCode> routeDrawModifier, ConfigEntry<float> routeEraseRadius, ConfigEntry<float> routeSnapRadius, ConfigEntry<float> routeOnRoadTolerance, ConfigEntry<float> routeOffRoadSpeed, ConfigEntry<float> routeOnRoadSpeed, ConfigEntry<float> uiScale, ConfigEntry<bool> highContrast, ConfigEntry<string> workbenchGamepadButton, ConfigEntry<string> drawerGamepadButton, ConfigEntry<bool> enhancedPinPalette, ConfigEntry<bool> showVanillaPinPalette, ConfigEntry<CrashConsentState> crashReportingConsent, ConfigEntry<int> acceptedPrivacyPolicyVersion, ConfigEntry<string> sentryDsn, ConfigEntry<bool> showVanillaMapControls, ConfigEntry<bool> highPrecisionLargeMapRoads) { Enabled = enabled; CaptureConstructionActions = captureConstructionActions; ReconcileTerrainChanges = reconcileTerrainChanges; SampleIntervalSeconds = sampleIntervalSeconds; MinimumPointSpacingMeters = minimumPointSpacingMeters; MaximumStrokeGapMeters = maximumStrokeGapMeters; DuplicateSuppressionMeters = duplicateSuppressionMeters; AutosaveIntervalSeconds = autosaveIntervalSeconds; PaintThreshold = paintThreshold; PaintSampleRadius = paintSampleRadius; LineWidthPixels = lineWidthPixels; DebugLogging = debugLogging; DrawCalibrationMarkers = drawCalibrationMarkers; WorkbenchHotkey = workbenchHotkey; DrawerHotkey = drawerHotkey; DrawerShowDirt = drawerShowDirt; DrawerShowPaved = drawerShowPaved; DrawerShowPins = drawerShowPins; DrawerCluster = drawerCluster; DrawerPanelPosition = drawerPanelPosition; QuickPinHotkey = quickPinHotkey; QuickPinDuplicateRadius = quickPinDuplicateRadius; SurveyRulesEnabled = surveyRulesEnabled; SurveyScanIntervalSeconds = surveyScanIntervalSeconds; SurveyScanRadius = surveyScanRadius; SurveyBaseExclusionRadius = surveyBaseExclusionRadius; SurveyMaxObservations = surveyMaxObservations; RouteDrawModifier = routeDrawModifier; RouteEraseRadius = routeEraseRadius; RouteSnapRadius = routeSnapRadius; RouteOnRoadTolerance = routeOnRoadTolerance; RouteOffRoadSpeed = routeOffRoadSpeed; RouteOnRoadSpeed = routeOnRoadSpeed; UiScale = uiScale; HighContrast = highContrast; WorkbenchGamepadButton = workbenchGamepadButton; DrawerGamepadButton = drawerGamepadButton; EnhancedPinPalette = enhancedPinPalette; ShowVanillaPinPalette = showVanillaPinPalette; CrashReportingConsent = crashReportingConsent; AcceptedPrivacyPolicyVersion = acceptedPrivacyPolicyVersion; SentryDsn = sentryDsn; ShowVanillaMapControls = showVanillaMapControls; HighPrecisionLargeMapRoads = highPrecisionLargeMapRoads; } public static CartographerSettings Bind(ConfigFile config) { //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Expected O, but got Unknown //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Expected O, but got Unknown //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Expected O, but got Unknown //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Expected O, but got Unknown //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Expected O, but got Unknown //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_0174: 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_01b8: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Expected O, but got Unknown //IL_02d1: Unknown result type (might be due to invalid IL or missing references) //IL_02db: Expected O, but got Unknown //IL_031a: Unknown result type (might be due to invalid IL or missing references) //IL_0324: Expected O, but got Unknown //IL_034d: Unknown result type (might be due to invalid IL or missing references) //IL_0357: Expected O, but got Unknown //IL_0380: Unknown result type (might be due to invalid IL or missing references) //IL_038a: Expected O, but got Unknown //IL_03b0: Unknown result type (might be due to invalid IL or missing references) //IL_03ba: Expected O, but got Unknown //IL_03fd: Unknown result type (might be due to invalid IL or missing references) //IL_0407: Expected O, but got Unknown //IL_0430: Unknown result type (might be due to invalid IL or missing references) //IL_043a: Expected O, but got Unknown //IL_0463: Unknown result type (might be due to invalid IL or missing references) //IL_046d: Expected O, but got Unknown //IL_0496: Unknown result type (might be due to invalid IL or missing references) //IL_04a0: Expected O, but got Unknown //IL_04c9: Unknown result type (might be due to invalid IL or missing references) //IL_04d3: Expected O, but got Unknown //IL_04fc: Unknown result type (might be due to invalid IL or missing references) //IL_0506: Expected O, but got Unknown return new CartographerSettings(config.Bind<bool>("General", "Enabled", true, "Enable road surveying and map overlays."), config.Bind<bool>("Sources", "CaptureConstructionActions", true, "Record roads from your own successful Pathen (hoe) and Paved (cultivator/stonecutter) actions. This is the ONLY road source: walking existing paint never creates roads."), config.Bind<bool>("Sources", "ReconcileTerrainChanges", true, "When you level, raise, cultivate, reset, or repaint terrain, remove the covered road ink from the atlas so no ghost roads remain."), config.Bind<float>("Survey", "SampleIntervalSeconds", 0.35f, new ConfigDescription("Seconds between diagnostic terrain samples under the player (feeds 'cc_roads align live'; never creates roads).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 5f), Array.Empty<object>())), config.Bind<float>("Survey", "MinimumPointSpacingMeters", 1.5f, new ConfigDescription("Minimum horizontal distance before a new road point is stored.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 20f), Array.Empty<object>())), config.Bind<float>("Survey", "MaximumStrokeGapMeters", 8f, new ConfigDescription("A larger gap starts a new stroke instead of drawing a long connector.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 100f), Array.Empty<object>())), config.Bind<float>("Survey", "DuplicateSuppressionMeters", 2f, new ConfigDescription("Skip samples within this distance of already-recorded road ink of the same kind, so re-walking a road never grows the atlas. 0 disables suppression; values above ~3 may also suppress tight hairpin switchbacks.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f), Array.Empty<object>())), config.Bind<float>("Persistence", "AutosaveIntervalSeconds", 15f, new ConfigDescription("Seconds between dirty-atlas autosaves.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 300f), Array.Empty<object>())), config.Bind<float>("Detection", "PaintThreshold", 0.4f, new ConfigDescription("Minimum averaged red/blue paint value used to identify roads.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 0.95f), Array.Empty<object>())), config.Bind<int>("Detection", "PaintSampleRadius", 1, new ConfigDescription("Terrain paint pixels sampled around the player (0 is a single pixel).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 3), Array.Empty<object>())), config.Bind<int>("Map", "LineWidthPixels", 1, new ConfigDescription("Road line width on the map overlay, in map texels. One texel covers ~11.6 m of world, so widths above 1 make nearby roads merge into blobs.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 6), Array.Empty<object>())), config.Bind<bool>("Diagnostics", "DebugLogging", false, "Write diagnostic road classification messages."), config.Bind<bool>("Diagnostics", "DrawCalibrationMarkers", false, "Draw fixed calibration crosses into the dirt overlay at world origin (magenta), +128m east (yellow), and +128m north (cyan) to verify overlay/map alignment."), config.Bind<KeyCode>("Workbench", "WorkbenchHotkey", (KeyCode)112, "Key that opens the Pin Workbench for the pin under the cursor while the large map is open."), config.Bind<KeyCode>("Drawer", "DrawerHotkey", (KeyCode)108, "Key that toggles the Atlas Drawer (layers, search, saved views) while the large map is open."), config.Bind<bool>("Drawer", "ShowDirtRoads", true, "Show the dirt-road layer."), config.Bind<bool>("Drawer", "ShowPavedRoads", true, "Show the paved-road layer."), config.Bind<bool>("Drawer", "ShowPins", true, "Show managed pins on the map."), config.Bind<bool>("Drawer", "Clustering", true, "Fold crowded pins into cluster markers when zoomed out (display only; never changes stored pins)."), config.Bind<string>("Drawer", "PanelPosition", "", "Internal: the Atlas drawer's last dragged position as \"x,y\" canvas offsets from its right-center anchor. Written when the drawer closes; empty uses the default dock. Restored positions are clamped on-screen, so editing this can never strand the panel."), config.Bind<KeyCode>("Workbench", "QuickPinHotkey", (KeyCode)288, "Key that pins the object you are looking at (set to None to disable). Never pins creatures."), config.Bind<float>("Workbench", "QuickPinDuplicateRadius", 25f, new ConfigDescription("Skip a quick pin when a same-named pin already exists within this many meters (0 disables the check).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 200f), Array.Empty<object>())), config.Bind<bool>("Survey", "SurveyRulesEnabled", false, "Opt-in survey rules: nearby loaded objects matching survey-rules.tsv become reviewable observations (never pins directly)."), config.Bind<float>("Survey", "SurveyScanIntervalSeconds", 10f, new ConfigDescription("Legacy, no effect since v1.0 RC10: the survey scans continuously on a bounded per-frame budget. Kept so existing config files load cleanly.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 60f), Array.Empty<object>())), config.Bind<float>("Survey", "SurveyScanRadius", 40f, new ConfigDescription("Survey scan radius around the player in meters.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 100f), Array.Empty<object>())), config.Bind<float>("Survey", "SurveyBaseExclusionRadius", 30f, new ConfigDescription("No observations within this distance of a pin categorized/tagged Base (0 disables).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>())), config.Bind<int>("Survey", "SurveyMaxObservations", 200, new ConfigDescription("Hard cap on pending survey observations.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(10, 1000), Array.Empty<object>())), config.Bind<KeyCode>("Routes", "RouteDrawModifier", (KeyCode)304, "Modifier held with LeftClick on the large map for route draw/erase/waypoint modes (avoids vanilla map-drag conflicts)."), config.Bind<float>("Routes", "RouteEraseRadius", 8f, new ConfigDescription("Route erase brush radius in meters.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 30f), Array.Empty<object>())), config.Bind<float>("Routes", "RouteSnapRadius", 15f, new ConfigDescription("Waypoints snap to roads within this many meters.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 50f), Array.Empty<object>())), config.Bind<float>("Routes", "RouteOnRoadTolerance", 6f, new ConfigDescription("A route counts as on-road when within this distance of recorded road ink.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 15f), Array.Empty<object>())), config.Bind<float>("Routes", "RouteOffRoadSpeed", 2.5f, new ConfigDescription("Off-road travel speed (m/s) for time estimates.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 15f), Array.Empty<object>())), config.Bind<float>("Routes", "RouteOnRoadSpeed", 5f, new ConfigDescription("On-road travel speed (m/s) for time estimates.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 15f), Array.Empty<object>())), config.Bind<float>("Accessibility", "UiScale", 1f, new ConfigDescription("Scale multiplier for Concerned Cartographer panels.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.8f, 1.6f), Array.Empty<object>())), config.Bind<bool>("Accessibility", "HighContrast", false, "High-contrast map ink: near-black dirt, near-white paved, brighter route colors. Kinds stay distinguishable without color (dashed/dotted styles, icons, labels)."), config.Bind<string>("Accessibility", "WorkbenchGamepadButton", "", "ZInput button name that opens the Pin Workbench (e.g. JoyLStick). Empty disables; conflicts are avoided by explicit opt-in."), config.Bind<string>("Accessibility", "DrawerGamepadButton", "", "ZInput button name that toggles the Atlas Drawer. Empty disables."), config.Bind<bool>("Pins", "EnhancedPinPalette", true, "Show the Concerned Cartographer marker palette on the large map. Markers created through it are managed from birth (no upgrade step)."), config.Bind<bool>("Pins", "ShowVanillaPinPalette", false, "Keep Valheim's own five pin-icon buttons visible alongside (or instead of) the enhanced palette. Automatically treated as true when a known conflicting pin manager is installed."), config.Bind<CrashConsentState>("Privacy", "SendCrashReports", CrashConsentState.Unknown, "Send anonymous crash reports when Concerned Cartographer hits an internal error. Unknown = not asked yet (a one-time dialog appears on the first large-map open); nothing is ever sent while Unknown or Disabled. What is and is not collected: PRIVACY.md. No gameplay analytics, ever."), config.Bind<int>("Privacy", "AcceptedPrivacyPolicyVersion", 0, "Internal: the crash-reporting policy version the player answered. Re-prompts only if the collected data categories materially change in a future release."), config.Bind<string>("Privacy", "SentryDsn", "", "Advanced: override the embedded crash-report ingestion DSN (a public event-submission key). Empty uses the built-in value; if both are empty, crash reporting is fully inert. NEVER put a Sentry auth token here."), config.Bind<bool>("Map", "ShowVanillaMapControls", false, "Show Valheim's own right-side map control rail (pin icon selectors, death/boss filter buttons, visible-to-others toggle) alongside the Concerned Cartographer toolbar. Default: the CC toolbar and Atlas System Markers replace it. Automatically treated as true when a known conflicting pin manager is installed."), config.Bind<bool>("Map", "HighPrecisionLargeMapRoads", true, "Render roads on the LARGE map as sub-texel vector geometry that pans/zooms with the map (DEF-v1.0-006), instead of only the 2048-texel texture overlay (which stays for the minimap and as fallback)