246 lines
No EOL
8.4 KiB
C#
246 lines
No EOL
8.4 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Drawing;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using Decal.Adapter;
|
|
using Microsoft.Win32;
|
|
|
|
namespace MosswartMassacre
|
|
{
|
|
public class NavVisualization : IDisposable
|
|
{
|
|
private bool disposed = false;
|
|
private NavRoute currentRoute = null;
|
|
private string vtankProfilesDirectory = "";
|
|
private List<string> availableNavFiles = new List<string>();
|
|
|
|
// Default comparison route color (red)
|
|
private readonly Color comparisonRouteColor = Color.FromArgb(255, 255, 100, 100);
|
|
|
|
public bool IsEnabled { get; private set; } = false;
|
|
public bool HasRouteLoaded => currentRoute != null && currentRoute.WaypointCount > 0;
|
|
public string CurrentRouteFile => currentRoute?.FileName ?? "None";
|
|
public List<string> AvailableNavFiles => availableNavFiles.ToList();
|
|
|
|
public event EventHandler RouteChanged;
|
|
|
|
public NavVisualization()
|
|
{
|
|
InitializeVTankDirectory();
|
|
RefreshNavFileList();
|
|
}
|
|
|
|
private void InitializeVTankDirectory()
|
|
{
|
|
try
|
|
{
|
|
// First, check if user has configured a custom path
|
|
if (!string.IsNullOrEmpty(PluginSettings.Instance?.VTankProfilesPath))
|
|
{
|
|
vtankProfilesDirectory = PluginSettings.Instance.VTankProfilesPath;
|
|
return;
|
|
}
|
|
|
|
// Try to get VTank directory from Windows Registry (same method as UtilityBelt)
|
|
var defaultPath = @"C:\Games\VirindiPlugins\VirindiTank\";
|
|
try
|
|
{
|
|
var regKey = Registry.LocalMachine.OpenSubKey("Software\\Decal\\Plugins\\{642F1F48-16BE-48BF-B1D4-286652C4533E}");
|
|
if (regKey != null)
|
|
{
|
|
var profilePath = regKey.GetValue("ProfilePath")?.ToString();
|
|
if (!string.IsNullOrEmpty(profilePath))
|
|
{
|
|
vtankProfilesDirectory = profilePath;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
|
|
// Fall back to default path
|
|
vtankProfilesDirectory = defaultPath;
|
|
// Using default path - user can configure in Settings if needed
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
PluginCore.WriteToChat($"[NavViz] Error finding VTank directory: {ex.Message}");
|
|
vtankProfilesDirectory = "";
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Scan VTank directory for .nav files and populate available routes list
|
|
/// Filters out follow files and temporary files, sorts alphabetically
|
|
/// </summary>
|
|
public void RefreshNavFileList()
|
|
{
|
|
// Re-initialize directory in case settings changed
|
|
InitializeVTankDirectory();
|
|
|
|
availableNavFiles.Clear();
|
|
|
|
|
|
if (string.IsNullOrEmpty(vtankProfilesDirectory))
|
|
{
|
|
PluginCore.WriteToChat("VTank directory not configured. Set path in Settings tab.");
|
|
return;
|
|
}
|
|
|
|
if (!Directory.Exists(vtankProfilesDirectory))
|
|
{
|
|
PluginCore.WriteToChat($"VTank directory not found: {vtankProfilesDirectory}");
|
|
return;
|
|
}
|
|
|
|
try
|
|
{
|
|
// Get all files and filter for .nav files only, excluding follow/temporary files
|
|
var allFiles = Directory.GetFiles(vtankProfilesDirectory);
|
|
var navFiles = allFiles
|
|
.Where(file => Path.GetExtension(file).Equals(".nav", StringComparison.OrdinalIgnoreCase))
|
|
.Select(file => Path.GetFileNameWithoutExtension(file))
|
|
.Where(name => !string.IsNullOrEmpty(name) &&
|
|
!name.StartsWith("follow", StringComparison.OrdinalIgnoreCase) &&
|
|
!name.StartsWith("--", StringComparison.OrdinalIgnoreCase))
|
|
.OrderBy(name => name)
|
|
.ToList();
|
|
|
|
availableNavFiles.AddRange(navFiles);
|
|
|
|
// Only report summary - no need to spam chat with every file
|
|
if (navFiles.Count > 0)
|
|
{
|
|
PluginCore.WriteToChat($"Navigation: Found {navFiles.Count} route files");
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
PluginCore.WriteToChat($"Navigation: Error scanning files - {ex.Message}");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Load a specific navigation route file for visualization
|
|
/// Clears current route if "None" specified, otherwise loads .nav file
|
|
/// </summary>
|
|
/// <param name="navFileName">Name of .nav file (without extension) or "None"</param>
|
|
/// <returns>True if route loaded successfully, false otherwise</returns>
|
|
public bool LoadRoute(string navFileName)
|
|
{
|
|
try
|
|
{
|
|
// Clear current route
|
|
if (currentRoute != null)
|
|
{
|
|
currentRoute.Dispose();
|
|
currentRoute = null;
|
|
}
|
|
|
|
if (string.IsNullOrEmpty(navFileName) || navFileName == "None")
|
|
{
|
|
RouteChanged?.Invoke(this, EventArgs.Empty);
|
|
return true;
|
|
}
|
|
|
|
string fullPath = Path.Combine(vtankProfilesDirectory, navFileName + ".nav");
|
|
|
|
if (!File.Exists(fullPath))
|
|
{
|
|
PluginCore.WriteToChat($"Navigation file '{navFileName}' not found");
|
|
return false;
|
|
}
|
|
|
|
currentRoute = new NavRoute(fullPath, comparisonRouteColor);
|
|
|
|
if (!currentRoute.LoadFromFile())
|
|
{
|
|
currentRoute.Dispose();
|
|
currentRoute = null;
|
|
return false;
|
|
}
|
|
|
|
// Show route if visualization is enabled
|
|
if (IsEnabled)
|
|
{
|
|
currentRoute.Show();
|
|
}
|
|
|
|
RouteChanged?.Invoke(this, EventArgs.Empty);
|
|
return true;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
PluginCore.WriteToChat($"Navigation: Failed to load '{navFileName}' - {ex.Message}");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Enable or disable navigation route visualization in 3D world
|
|
/// Shows/hides the currently loaded route based on enabled state
|
|
/// </summary>
|
|
/// <param name="enabled">True to show route lines, false to hide</param>
|
|
public void SetEnabled(bool enabled)
|
|
{
|
|
// No change needed if already in desired state
|
|
if (IsEnabled == enabled) return;
|
|
|
|
IsEnabled = enabled;
|
|
|
|
if (currentRoute != null)
|
|
{
|
|
if (enabled)
|
|
{
|
|
currentRoute.Show();
|
|
}
|
|
else
|
|
{
|
|
currentRoute.Hide();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
}
|
|
|
|
PluginCore.WriteToChat($"Navigation visualization {(enabled ? "enabled" : "disabled")}");
|
|
}
|
|
|
|
public void ToggleEnabled()
|
|
{
|
|
SetEnabled(!IsEnabled);
|
|
}
|
|
|
|
public string GetStatus()
|
|
{
|
|
if (currentRoute == null)
|
|
return "No route loaded";
|
|
|
|
string status = $"{currentRoute.FileName} ({currentRoute.WaypointCount} points)";
|
|
if (IsEnabled && currentRoute.IsVisible)
|
|
status += " - Visible";
|
|
else if (IsEnabled)
|
|
status += " - Hidden";
|
|
else
|
|
status += " - Disabled";
|
|
|
|
return status;
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
if (!disposed)
|
|
{
|
|
if (currentRoute != null)
|
|
{
|
|
currentRoute.Dispose();
|
|
currentRoute = null;
|
|
}
|
|
disposed = true;
|
|
}
|
|
}
|
|
}
|
|
} |