MosswartMassacre/MosswartMassacre/Views/TabbedMainView.cs
2025-05-29 17:58:56 +02:00

794 lines
No EOL
30 KiB
C#

using System;
using System.Drawing;
using System.Timers;
using MyClasses.MetaViewWrappers;
namespace MosswartMassacre.Views
{
internal class TabbedMainView : BaseView
{
private static TabbedMainView instance;
// Main tab controls (existing functionality)
private IStaticText lblTotalKills;
private IStaticText lblKillsPer5Min;
private IStaticText lblKillsPerHour;
private IStaticText lblElapsedTime;
private IStaticText lblRareCount;
private IStaticText lblAutoLootRare;
private IStaticText lblStatus;
private IStaticText lblWebSocketStatus;
// Settings tab controls
private ICheckBox chkRareMetaEnabled;
private ICheckBox chkRemoteCommandsEnabled;
private ICheckBox chkHttpServerEnabled;
private ICheckBox chkWebSocketEnabled;
private ICheckBox chkTelemetryEnabled;
private ITextBox txtCharTag;
private ITextBox txtVTankPath;
// Statistics tab controls
private IStaticText lblDetailedKillsValue;
private IStaticText lblBestHourValue;
private IStaticText lblAverageKillsValue;
private IStaticText lblRareStatsValue;
private IStaticText lblRareRateValue;
private IStaticText lblSessionTimeValue;
private IStaticText lblLastKillValue;
private IButton btnResetStats;
// Navigation tab controls
private ICheckBox chkNavVisualizationEnabled;
private ICombo cmbNavFiles;
private IButton btnRefreshNavFiles;
private IStaticText lblNavStatus;
private IButton btnLoadRoute;
private IButton btnClearRoute;
// Position tracking
private Timer positionSaveTimer;
private Timer positionCheckTimer;
private Point lastKnownPosition;
// Statistics tracking
private double bestHourlyKills = 0;
private DateTime sessionStartTime;
public TabbedMainView(PluginCore core) : base(core)
{
instance = this;
sessionStartTime = DateTime.Now;
InitializePositionTimer();
}
private void InitializePositionTimer()
{
positionSaveTimer = new Timer(2000);
positionSaveTimer.Elapsed += (s, e) => {
SaveWindowPosition();
positionSaveTimer.Stop();
};
positionCheckTimer = new Timer(500);
positionCheckTimer.Elapsed += CheckPositionChanged;
positionCheckTimer.Start();
}
public static void ViewInit()
{
try
{
if (instance == null)
{
instance = new TabbedMainView(null);
}
instance.InitializeView();
PluginCore.WriteToChat("Enhanced tabbed view initialized.");
}
catch (Exception ex)
{
PluginCore.WriteToChat("Error initializing tabbed view: " + ex.Message);
}
}
private void InitializeView()
{
try
{
// Load the new tabbed view
CreateFromXMLResource("MosswartMassacre.ViewXML.mainViewTabbed.xml");
InitializeMainTabControls();
InitializeSettingsTabControls();
InitializeStatisticsTabControls();
InitializeNavigationTabControls();
// Initialize the base view and set initial position
Initialize();
lastKnownPosition = view?.Location ?? new Point(100, 100);
}
catch (Exception ex)
{
PluginCore.WriteToChat("Error in InitializeView: " + ex.Message);
}
}
private void InitializeMainTabControls()
{
try
{
// Main tab - existing functionality
lblTotalKills = (IStaticText)view["lblTotalKills"];
lblKillsPer5Min = (IStaticText)view["lblKillsPer5Min"];
lblKillsPerHour = (IStaticText)view["lblKillsPerHour"];
lblElapsedTime = (IStaticText)view["lblElapsedTime"];
lblRareCount = (IStaticText)view["lblRareCount"];
lblAutoLootRare = (IStaticText)view["lblAutoLootRare"];
lblStatus = (IStaticText)view["lblStatus"];
lblWebSocketStatus = (IStaticText)view["lblWebSocketStatus"];
// Update status, auto loot indicator, and websocket status immediately
UpdateStatus();
UpdateAutoLootRareIndicator();
UpdateWebSocketStatus();
}
catch (Exception ex)
{
PluginCore.WriteToChat($"Error initializing main tab controls: {ex.Message}");
}
}
private void InitializeSettingsTabControls()
{
// Settings tab controls
chkRareMetaEnabled = (ICheckBox)view["chkRareMetaEnabled"];
chkRemoteCommandsEnabled = (ICheckBox)view["chkRemoteCommandsEnabled"];
chkHttpServerEnabled = (ICheckBox)view["chkHttpServerEnabled"];
chkWebSocketEnabled = (ICheckBox)view["chkWebSocketEnabled"];
chkTelemetryEnabled = (ICheckBox)view["chkTelemetryEnabled"];
txtCharTag = (ITextBox)view["txtCharTag"];
txtVTankPath = (ITextBox)view["txtVTankPath"];
// Hook up settings events
chkRareMetaEnabled.Change += OnRareMetaSettingChanged;
chkRemoteCommandsEnabled.Change += OnRemoteCommandsSettingChanged;
chkHttpServerEnabled.Change += OnHttpServerSettingChanged;
chkWebSocketEnabled.Change += OnWebSocketSettingChanged;
chkTelemetryEnabled.Change += OnTelemetrySettingChanged;
txtCharTag.Change += OnCharTagChanged;
txtVTankPath.Change += OnVTankPathChanged;
// Load current settings
LoadCurrentSettings();
}
private void InitializeStatisticsTabControls()
{
try
{
// Statistics tab controls
lblDetailedKillsValue = (IStaticText)view["lblDetailedKillsValue"];
lblBestHourValue = (IStaticText)view["lblBestHourValue"];
lblAverageKillsValue = (IStaticText)view["lblAverageKillsValue"];
lblRareStatsValue = (IStaticText)view["lblRareStatsValue"];
lblRareRateValue = (IStaticText)view["lblRareRateValue"];
lblSessionTimeValue = (IStaticText)view["lblSessionTimeValue"];
lblLastKillValue = (IStaticText)view["lblLastKillValue"];
btnResetStats = (IButton)view["btnResetStats"];
// Hook up statistics events
if (btnResetStats != null)
btnResetStats.Hit += OnResetStatsClick;
}
catch (Exception ex)
{
PluginCore.WriteToChat($"Error initializing statistics controls: {ex.Message}");
}
}
private void InitializeNavigationTabControls()
{
try
{
// Navigation tab controls
chkNavVisualizationEnabled = (ICheckBox)view["chkNavVisualizationEnabled"];
cmbNavFiles = (ICombo)view["cmbNavFiles"];
btnRefreshNavFiles = (IButton)view["btnRefreshNavFiles"];
lblNavStatus = (IStaticText)view["lblNavStatus"];
btnLoadRoute = (IButton)view["btnLoadRoute"];
btnClearRoute = (IButton)view["btnClearRoute"];
// Hook up navigation events
if (chkNavVisualizationEnabled != null)
chkNavVisualizationEnabled.Change += OnNavVisualizationEnabledChanged;
if (btnRefreshNavFiles != null)
btnRefreshNavFiles.Hit += OnRefreshNavFilesClick;
if (btnLoadRoute != null)
btnLoadRoute.Hit += OnLoadRouteClick;
if (btnClearRoute != null)
btnClearRoute.Hit += OnClearRouteClick;
// Initialize navigation system
InitializeNavigationSystem();
}
catch (Exception ex)
{
PluginCore.WriteToChat($"Error initializing navigation controls: {ex.Message}");
}
}
#region Event Handlers - Main Tab
// No main tab event handlers needed anymore - buttons removed
#endregion
#region Event Handlers - Settings Tab
private void OnRareMetaSettingChanged(object sender, EventArgs e)
{
PluginSettings.Instance.RareMetaEnabled = chkRareMetaEnabled.Checked;
PluginCore.RareMetaEnabled = chkRareMetaEnabled.Checked; // Update the static property too
UpdateAutoLootRareIndicator();
// Add chat message like websockets
PluginCore.WriteToChat($"Rare meta automation {(chkRareMetaEnabled.Checked ? "ENABLED" : "DISABLED")}.");
}
private void OnRemoteCommandsSettingChanged(object sender, EventArgs e)
{
PluginSettings.Instance.RemoteCommandsEnabled = chkRemoteCommandsEnabled.Checked;
}
private void OnHttpServerSettingChanged(object sender, EventArgs e)
{
PluginSettings.Instance.HttpServerEnabled = chkHttpServerEnabled.Checked;
if (chkHttpServerEnabled.Checked)
HttpCommandServer.Start();
else
HttpCommandServer.Stop();
}
private void OnWebSocketSettingChanged(object sender, EventArgs e)
{
PluginSettings.Instance.WebSocketEnabled = chkWebSocketEnabled.Checked;
if (chkWebSocketEnabled.Checked)
{
WebSocket.Start();
PluginCore.WriteToChat("WebSocket streaming ENABLED.");
}
else
{
WebSocket.Stop();
PluginCore.WriteToChat("WebSocket streaming DISABLED.");
}
UpdateWebSocketStatus();
}
private void OnTelemetrySettingChanged(object sender, EventArgs e)
{
PluginSettings.Instance.TelemetryEnabled = chkTelemetryEnabled.Checked;
if (chkTelemetryEnabled.Checked)
Telemetry.Start();
else
Telemetry.Stop();
}
private void OnCharTagChanged(object sender, EventArgs e)
{
PluginSettings.Instance.CharTag = txtCharTag.Text;
}
private void OnVTankPathChanged(object sender, EventArgs e)
{
PluginSettings.Instance.VTankProfilesPath = txtVTankPath.Text;
// Refresh navigation system with new path
if (PluginCore.navVisualization != null)
{
PluginCore.navVisualization.RefreshNavFileList();
// Also refresh the dropdown list in Navigation tab
RefreshNavFileList();
UpdateNavigationStatus();
}
}
// Settings save automatically via property setters - no manual save/reset buttons needed
private void LoadCurrentSettings()
{
try
{
if (PluginSettings.Instance != null && chkRareMetaEnabled != null)
{
chkRareMetaEnabled.Checked = PluginSettings.Instance.RareMetaEnabled;
chkRemoteCommandsEnabled.Checked = PluginSettings.Instance.RemoteCommandsEnabled;
chkHttpServerEnabled.Checked = PluginSettings.Instance.HttpServerEnabled;
chkWebSocketEnabled.Checked = PluginSettings.Instance.WebSocketEnabled;
chkTelemetryEnabled.Checked = PluginSettings.Instance.TelemetryEnabled;
txtCharTag.Text = PluginSettings.Instance.CharTag ?? "default";
txtVTankPath.Text = PluginSettings.Instance.VTankProfilesPath ?? "";
}
}
catch (Exception ex)
{
PluginCore.WriteToChat($"Error loading settings: {ex.Message}");
}
}
#endregion
#region Event Handlers - Statistics Tab
private void OnResetStatsClick(object sender, EventArgs e)
{
// Reset stats functionality moved here from removed OnRestartClick
PluginCore.RestartStats();
sessionStartTime = DateTime.Now;
bestHourlyKills = 0;
UpdateStatistics();
}
#endregion
#region Event Handlers - Navigation Tab
private void OnNavVisualizationEnabledChanged(object sender, EventArgs e)
{
if (PluginCore.navVisualization != null)
{
PluginCore.navVisualization.SetEnabled(chkNavVisualizationEnabled.Checked);
UpdateNavigationStatus();
}
}
private void OnRefreshNavFilesClick(object sender, EventArgs e)
{
RefreshNavFileList();
}
private void OnLoadRouteClick(object sender, EventArgs e)
{
try
{
if (cmbNavFiles != null && PluginCore.navVisualization != null &&
cmbNavFiles.Selected >= 0 && cmbNavFiles.Count > 0 &&
cmbNavFiles.Selected < cmbNavFiles.Count)
{
string selectedFile = cmbNavFiles.Text[cmbNavFiles.Selected];
if (selectedFile != "None" && !string.IsNullOrEmpty(selectedFile))
{
PluginCore.navVisualization.LoadRoute(selectedFile);
UpdateNavigationStatus();
}
else
{
PluginCore.WriteToChat("[NavViz] Please select a valid nav file from the dropdown");
}
}
else
{
PluginCore.WriteToChat("[NavViz] No nav files available. Click Refresh or configure VTank path in Settings tab");
}
}
catch (Exception ex)
{
PluginCore.WriteToChat($"[NavViz] Error loading route: {ex.Message}");
}
}
private void OnClearRouteClick(object sender, EventArgs e)
{
if (PluginCore.navVisualization != null)
{
PluginCore.navVisualization.LoadRoute("None");
if (cmbNavFiles != null)
{
cmbNavFiles.Selected = 0; // Select "None" which should be at index 0
}
UpdateNavigationStatus();
}
}
private void InitializeNavigationSystem()
{
try
{
RefreshNavFileList();
UpdateNavigationStatus();
// Subscribe to route changes
if (PluginCore.navVisualization != null)
{
PluginCore.navVisualization.RouteChanged += (s, e) => UpdateNavigationStatus();
}
}
catch (Exception ex)
{
PluginCore.WriteToChat($"Error initializing navigation system: {ex.Message}");
}
}
private void RefreshNavFileList()
{
try
{
if (PluginCore.navVisualization != null && cmbNavFiles != null)
{
PluginCore.navVisualization.RefreshNavFileList();
cmbNavFiles.Clear();
cmbNavFiles.Add("None");
foreach (string navFile in PluginCore.navVisualization.AvailableNavFiles)
{
PluginCore.WriteToChat($"[NavViz UI] Adding to dropdown: {navFile}");
cmbNavFiles.Add(navFile);
}
if (cmbNavFiles.Count > 0)
cmbNavFiles.Selected = 0; // Select "None" which should be at index 0
PluginCore.WriteToChat($"[NavViz UI] Dropdown populated with {cmbNavFiles.Count} items (including 'None')");
}
}
catch (Exception ex)
{
PluginCore.WriteToChat($"Error refreshing nav file list: {ex.Message}");
}
}
private void UpdateNavigationStatus()
{
try
{
if (lblNavStatus != null && PluginCore.navVisualization != null)
{
lblNavStatus.Text = $"Status: {PluginCore.navVisualization.GetStatus()}";
}
}
catch (Exception ex)
{
PluginCore.WriteToChat($"Error updating navigation status: {ex.Message}");
}
}
#endregion
#region Position Management
private void CheckPositionChanged(object sender, ElapsedEventArgs e)
{
try
{
if (view != null)
{
Point currentPosition = view.Location;
if (currentPosition != lastKnownPosition)
{
lastKnownPosition = currentPosition;
if (positionSaveTimer != null)
{
positionSaveTimer.Stop();
positionSaveTimer.Start();
}
}
}
}
catch
{
// Ignore errors in position checking
}
}
protected override void SaveWindowPosition()
{
try
{
if (view != null && PluginSettings.Instance != null)
{
PluginSettings.Instance.MainWindowX = view.Location.X;
PluginSettings.Instance.MainWindowY = view.Location.Y;
}
}
catch (Exception ex)
{
PluginCore.WriteToChat($"Error saving window position: {ex.Message}");
}
}
protected override void RestoreWindowPosition()
{
try
{
if (view != null && PluginSettings.Instance != null)
{
view.Location = new Point(
PluginSettings.Instance.MainWindowX,
PluginSettings.Instance.MainWindowY
);
}
}
catch (Exception ex)
{
PluginCore.WriteToChat($"Error restoring window position: {ex.Message}");
}
}
#endregion
#region Public Update Methods (maintain compatibility with existing code)
public static void UpdateKillStats(int totalKills, double killsPer5Min, double killsPerHour)
{
try
{
if (instance?.lblTotalKills != null)
{
instance.lblTotalKills.Text = $"Total Kills: {totalKills}";
}
if (instance?.lblKillsPer5Min != null)
{
instance.lblKillsPer5Min.Text = $"Kills per 5 Min: {killsPer5Min:F2}";
}
if (instance?.lblKillsPerHour != null)
{
instance.lblKillsPerHour.Text = $"Kills per Hour: {killsPerHour:F2}";
}
// Update detailed statistics
if (instance?.lblDetailedKillsValue != null)
{
instance.lblDetailedKillsValue.Text = totalKills.ToString();
}
if (instance?.lblAverageKillsValue != null)
{
instance.lblAverageKillsValue.Text = $"{killsPerHour:F2} kills/hr";
}
// Track best hourly performance
if (instance != null && killsPerHour > instance.bestHourlyKills)
{
instance.bestHourlyKills = killsPerHour;
if (instance.lblBestHourValue != null)
{
instance.lblBestHourValue.Text = $"{instance.bestHourlyKills:F2} kills/hr";
}
}
// Update status and auto loot indicator
instance?.UpdateStatus();
instance?.UpdateAutoLootRareIndicator();
instance?.UpdateWebSocketStatus();
instance?.UpdateStatistics();
}
catch (Exception ex)
{
PluginCore.WriteToChat($"Error in UpdateKillStats: {ex.Message}");
}
}
public static void UpdateElapsedTime(TimeSpan elapsed)
{
try
{
if (instance?.lblElapsedTime != null)
{
int days = elapsed.Days;
int hours = elapsed.Hours;
int minutes = elapsed.Minutes;
int seconds = elapsed.Seconds;
if (days > 0)
instance.lblElapsedTime.Text = $"Time: {days}d {hours:D2}:{minutes:D2}:{seconds:D2}";
else
instance.lblElapsedTime.Text = $"Time: {hours:D2}:{minutes:D2}:{seconds:D2}";
}
if (instance?.lblSessionTimeValue != null && instance?.lblElapsedTime != null)
{
instance.lblSessionTimeValue.Text = instance.lblElapsedTime.Text.Replace("Time: ", "");
}
}
catch (Exception ex)
{
PluginCore.WriteToChat($"Error in UpdateElapsedTime: {ex.Message}");
}
}
public static void UpdateRareCount(int rareCount)
{
try
{
if (instance?.lblRareCount != null)
{
instance.lblRareCount.Text = $"Rare Count: {rareCount}";
}
if (instance?.lblRareStatsValue != null)
{
instance.lblRareStatsValue.Text = rareCount.ToString();
}
// Calculate rare drop rate
int totalKills = PluginCore.totalKills;
if (totalKills > 0 && instance?.lblRareRateValue != null)
{
double rareRate = (double)rareCount / totalKills * 100;
instance.lblRareRateValue.Text = $"{rareRate:F2}%";
}
}
catch (Exception ex)
{
PluginCore.WriteToChat($"Error in UpdateRareCount: {ex.Message}");
}
}
public static void SetRareMetaToggleState(bool enabled)
{
if (instance?.chkRareMetaEnabled != null)
{
instance.chkRareMetaEnabled.Checked = enabled;
}
instance?.UpdateAutoLootRareIndicator();
}
public static void RefreshSettingsFromConfig()
{
// Call this after settings are loaded to refresh UI
instance?.LoadCurrentSettings();
instance?.UpdateAutoLootRareIndicator();
instance?.UpdateWebSocketStatus();
}
private void UpdateStatus()
{
try
{
if (lblStatus != null)
{
string metaState = VtankControl.VtGetMetaState();
lblStatus.Text = $"Meta State: {metaState}";
}
}
catch
{
if (lblStatus != null)
lblStatus.Text = "Meta State: Unknown";
}
}
private void UpdateAutoLootRareIndicator()
{
try
{
if (lblAutoLootRare != null)
{
bool isEnabled = PluginSettings.Instance?.RareMetaEnabled == true;
if (isEnabled)
{
lblAutoLootRare.Text = "Auto Loot Rare: [ON]";
}
else
{
lblAutoLootRare.Text = "Auto Loot Rare: [OFF]";
}
}
}
catch
{
if (lblAutoLootRare != null)
lblAutoLootRare.Text = "Auto Loot Rare: Unknown";
}
}
private void UpdateWebSocketStatus()
{
try
{
if (lblWebSocketStatus != null)
{
bool isConnected = PluginSettings.Instance?.WebSocketEnabled == true;
if (isConnected)
{
lblWebSocketStatus.Text = "WebSocket: [CONNECTED]";
}
else
{
lblWebSocketStatus.Text = "WebSocket: [DISCONNECTED]";
}
}
}
catch
{
if (lblWebSocketStatus != null)
lblWebSocketStatus.Text = "WebSocket: Unknown";
}
}
#endregion
private void UpdateStatistics()
{
try
{
// Update last kill time
if (lblLastKillValue != null)
{
if (PluginCore.lastKillTime != DateTime.MinValue)
{
TimeSpan timeSinceLastKill = DateTime.Now - PluginCore.lastKillTime;
if (timeSinceLastKill.TotalMinutes < 60)
lblLastKillValue.Text = $"{timeSinceLastKill.TotalMinutes:F0} min ago";
else
lblLastKillValue.Text = $"{timeSinceLastKill.TotalHours:F1} hr ago";
}
else
{
lblLastKillValue.Text = "Never";
}
}
}
catch (Exception ex)
{
PluginCore.WriteToChat($"Error in UpdateStatistics: {ex.Message}");
}
}
public static void ViewDestroy()
{
try
{
if (instance != null)
{
// Save final position before destruction
instance.SaveWindowPosition();
// No main tab event handlers to clean up - buttons removed
// Clean up event handlers - Settings tab
if (instance.chkRareMetaEnabled != null)
instance.chkRareMetaEnabled.Change -= instance.OnRareMetaSettingChanged;
if (instance.chkRemoteCommandsEnabled != null)
instance.chkRemoteCommandsEnabled.Change -= instance.OnRemoteCommandsSettingChanged;
if (instance.chkHttpServerEnabled != null)
instance.chkHttpServerEnabled.Change -= instance.OnHttpServerSettingChanged;
if (instance.chkWebSocketEnabled != null)
instance.chkWebSocketEnabled.Change -= instance.OnWebSocketSettingChanged;
if (instance.chkTelemetryEnabled != null)
instance.chkTelemetryEnabled.Change -= instance.OnTelemetrySettingChanged;
if (instance.txtCharTag != null)
instance.txtCharTag.Change -= instance.OnCharTagChanged;
if (instance.txtVTankPath != null)
instance.txtVTankPath.Change -= instance.OnVTankPathChanged;
// Clean up event handlers - Statistics tab
if (instance.btnResetStats != null)
instance.btnResetStats.Hit -= instance.OnResetStatsClick;
// Clean up event handlers - Navigation tab
if (instance.chkNavVisualizationEnabled != null)
instance.chkNavVisualizationEnabled.Change -= instance.OnNavVisualizationEnabledChanged;
if (instance.btnRefreshNavFiles != null)
instance.btnRefreshNavFiles.Hit -= instance.OnRefreshNavFilesClick;
if (instance.btnLoadRoute != null)
instance.btnLoadRoute.Hit -= instance.OnLoadRouteClick;
if (instance.btnClearRoute != null)
instance.btnClearRoute.Hit -= instance.OnClearRouteClick;
// Clean up timers
if (instance.positionSaveTimer != null)
{
instance.positionSaveTimer.Stop();
instance.positionSaveTimer.Dispose();
instance.positionSaveTimer = null;
}
if (instance.positionCheckTimer != null)
{
instance.positionCheckTimer.Stop();
instance.positionCheckTimer.Dispose();
instance.positionCheckTimer = null;
}
instance.Dispose();
instance = null;
PluginCore.WriteToChat("Enhanced tabbed view destroyed.");
}
}
catch (Exception ex)
{
PluginCore.WriteToChat("Error destroying tabbed view: " + ex.Message);
}
}
}
}