diff --git a/MosswartMassacre/MosswartMassacre.csproj b/MosswartMassacre/MosswartMassacre.csproj index b2d0613..b200028 100644 --- a/MosswartMassacre/MosswartMassacre.csproj +++ b/MosswartMassacre/MosswartMassacre.csproj @@ -29,7 +29,7 @@ pdbonly true bin\Release\ - TRACE + TRACE;VVS_REFERENCED;DECAL_INTEROP prompt 4 @@ -175,14 +175,9 @@ True Resources.resx - - - + + - - - - diff --git a/MosswartMassacre/NavRoute.cs b/MosswartMassacre/NavRoute.cs index f1d0fa3..6f3ccfa 100644 --- a/MosswartMassacre/NavRoute.cs +++ b/MosswartMassacre/NavRoute.cs @@ -48,25 +48,23 @@ namespace MosswartMassacre return false; } - PluginCore.WriteToChat($"[NavRoute] Loading {FileName}..."); + PluginCore.WriteToChat($"Navigation: Loading {FileName}..."); using (StreamReader sr = File.OpenText(FilePath)) { // Read header string header = sr.ReadLine(); - PluginCore.WriteToChat($"[NavRoute] Header: '{header}'"); if (string.IsNullOrEmpty(header) || !header.StartsWith("uTank2 NAV")) { - PluginCore.WriteToChat($"Invalid nav file format: {FileName} (header: {header})"); + PluginCore.WriteToChat($"Navigation: Invalid file format - {FileName}"); return false; } // Read nav type string navTypeLine = sr.ReadLine(); - PluginCore.WriteToChat($"[NavRoute] Nav type line: '{navTypeLine}'"); if (string.IsNullOrEmpty(navTypeLine) || !int.TryParse(navTypeLine.Trim(), out int navType)) { - PluginCore.WriteToChat($"Could not parse nav type: {FileName} (line: '{navTypeLine}')"); + PluginCore.WriteToChat($"Navigation: Failed to parse route type - {FileName}"); return false; } @@ -90,46 +88,43 @@ namespace MosswartMassacre break; default: navTypeDescription = $"Unknown ({navType})"; - PluginCore.WriteToChat($"[NavRoute] WARNING: Unknown nav type {navType} in {FileName}"); + PluginCore.WriteToChat($"Navigation: Unknown route type {navType} in {FileName}"); break; } - - PluginCore.WriteToChat($"[NavRoute] Nav type: {navTypeDescription}"); // Handle target nav (type 3) - follows a specific player/object if (navType == 3) { if (sr.EndOfStream) { - PluginCore.WriteToChat($"[NavRoute] Target nav file is empty: {FileName}"); + PluginCore.WriteToChat($"Navigation: Target route file is empty - {FileName}"); return false; } string targetName = sr.ReadLine(); if (sr.EndOfStream) { - PluginCore.WriteToChat($"[NavRoute] Target nav missing target ID: {FileName}"); + PluginCore.WriteToChat($"Navigation: Target route missing target ID - {FileName}"); return false; } string targetIdLine = sr.ReadLine(); - PluginCore.WriteToChat($"[NavRoute] Target navigation for '{targetName}' (ID: {targetIdLine}) - No visual representation available"); + PluginCore.WriteToChat($"Navigation: Target route '{targetName}' cannot be visualized"); return true; // Successfully loaded but can't visualize } // Read record count string recordCountLine = sr.ReadLine(); - PluginCore.WriteToChat($"[NavRoute] Record count line: '{recordCountLine}'"); if (string.IsNullOrEmpty(recordCountLine) || !int.TryParse(recordCountLine.Trim(), out int recordCount)) { - PluginCore.WriteToChat($"Could not parse record count: {FileName} (line: '{recordCountLine}')"); + PluginCore.WriteToChat($"Navigation: Failed to parse waypoint count - {FileName}"); return false; } if (recordCount <= 0 || recordCount > 10000) // Sanity check { - PluginCore.WriteToChat($"Invalid record count: {recordCount} in {FileName}"); + PluginCore.WriteToChat($"Navigation: Invalid waypoint count {recordCount} - {FileName}"); return false; } @@ -138,33 +133,14 @@ namespace MosswartMassacre while (!sr.EndOfStream && waypointsRead < recordCount) { - PluginCore.WriteToChat($"[NavRoute] Reading waypoint {waypointsRead + 1}/{recordCount}"); - // Read waypoint type string waypointTypeLine = sr.ReadLine(); - PluginCore.WriteToChat($"[NavRoute] Waypoint type line: '{waypointTypeLine}'"); if (string.IsNullOrEmpty(waypointTypeLine) || !int.TryParse(waypointTypeLine.Trim(), out int waypointType)) { - PluginCore.WriteToChat($"Could not parse waypoint type at waypoint {waypointsRead}: '{waypointTypeLine}'"); + PluginCore.WriteToChat($"Navigation: Failed to parse waypoint {waypointsRead + 1} in {FileName}"); break; // Skip this waypoint, don't fail entirely } - - string waypointTypeDesc = waypointType switch - { - 0 => "Point", - 1 => "Portal", - 2 => "Recall", - 3 => "Pause", - 4 => "ChatCommand", - 5 => "OpenVendor", - 6 => "Portal2", - 7 => "UseNPC", - 8 => "Checkpoint", - 9 => "Jump", - _ => $"Unknown ({waypointType})" - }; - PluginCore.WriteToChat($"[NavRoute] Waypoint {waypointsRead + 1}: Type {waypointType} ({waypointTypeDesc})"); // Read coordinates (all waypoint types have EW, NS, Z, Unknown) string ewLine = sr.ReadLine(); @@ -172,11 +148,9 @@ namespace MosswartMassacre string zLine = sr.ReadLine(); string unknownLine = sr.ReadLine(); // Unknown value (always 0) - PluginCore.WriteToChat($"[NavRoute] Coordinates: EW={ewLine}, NS={nsLine}, Z={zLine}, Unknown={unknownLine}"); - if (string.IsNullOrEmpty(ewLine) || string.IsNullOrEmpty(nsLine) || string.IsNullOrEmpty(zLine) || string.IsNullOrEmpty(unknownLine)) { - PluginCore.WriteToChat($"Missing coordinate lines at waypoint {waypointsRead}"); + PluginCore.WriteToChat($"Navigation: Missing coordinates at waypoint {waypointsRead + 1} in {FileName}"); break; } @@ -184,7 +158,7 @@ namespace MosswartMassacre !double.TryParse(nsLine.Trim(), out double ns) || !double.TryParse(zLine.Trim(), out double z)) { - PluginCore.WriteToChat($"Could not parse coordinates at waypoint {waypointsRead}: EW={ewLine}, NS={nsLine}, Z={zLine}"); + PluginCore.WriteToChat($"Navigation: Invalid coordinates at waypoint {waypointsRead + 1} in {FileName}"); break; // Skip this waypoint } @@ -204,17 +178,18 @@ namespace MosswartMassacre // Skip additional data based on waypoint type if (!SkipWaypointData(sr, waypointType)) { - PluginCore.WriteToChat($"Failed to skip waypoint data for type {waypointType} at waypoint {waypointsRead}"); + PluginCore.WriteToChat($"Navigation: Failed to parse waypoint {waypointsRead + 1} data in {FileName}"); break; // Don't continue if we can't parse properly } } - PluginCore.WriteToChat($"[NavRoute] Loaded {waypoints.Count} waypoints from {FileName}"); - - // Debug: Show if we have waypoints to visualize if (waypoints.Count > 0) { - PluginCore.WriteToChat($"[NavRoute] Route ready for visualization with {waypoints.Count} waypoints"); + PluginCore.WriteToChat($"Navigation: Loaded {FileName} ({waypoints.Count} waypoints)"); + } + else + { + PluginCore.WriteToChat($"Navigation: No valid waypoints found in {FileName}"); } return waypoints.Count > 0; @@ -222,7 +197,7 @@ namespace MosswartMassacre } catch (Exception ex) { - PluginCore.WriteToChat($"[NavRoute] Error loading nav file {FileName}: {ex.Message}"); + PluginCore.WriteToChat($"Navigation: Error loading {FileName} - {ex.Message}"); return false; } } @@ -281,39 +256,31 @@ namespace MosswartMassacre sr.ReadLine(); // Milliseconds break; default: - PluginCore.WriteToChat($"[NavRoute] Unknown waypoint type: {waypointType}"); + // Unknown waypoint type - skip silently break; } return true; } - catch (Exception ex) + catch { - PluginCore.WriteToChat($"[NavRoute] Error skipping waypoint data: {ex.Message}"); + // Silently handle parsing errors return false; } } public void Show() { - PluginCore.WriteToChat($"[NavRoute] Show() called for {FileName}"); - PluginCore.WriteToChat($"[NavRoute] isVisible: {isVisible}, waypoints.Count: {waypoints.Count}"); - - if (isVisible) - { - PluginCore.WriteToChat($"[NavRoute] Route {FileName} is already visible, skipping"); - return; - } + if (isVisible) return; if (waypoints.Count == 0) { - PluginCore.WriteToChat($"[NavRoute] Route {FileName} has no waypoints to visualize"); + PluginCore.WriteToChat($"Navigation: No waypoints to visualize in {FileName}"); return; } - PluginCore.WriteToChat($"[NavRoute] Creating line objects for {FileName}..."); CreateLineObjects(); isVisible = true; - PluginCore.WriteToChat($"[NavRoute] Route {FileName} visualization complete - isVisible: {isVisible}"); + PluginCore.WriteToChat($"Navigation: Showing {FileName} ({waypoints.Count} waypoints)"); } public void Hide() @@ -322,34 +289,28 @@ namespace MosswartMassacre ClearRoute(); isVisible = false; - PluginCore.WriteToChat($"Hidden route: {FileName}"); + PluginCore.WriteToChat($"Navigation: Hidden {FileName}"); } private void CreateLineObjects() { try { - PluginCore.WriteToChat($"[NavRoute] CreateLineObjects() starting for {FileName}"); - // Check D3DService availability if (CoreManager.Current?.D3DService == null) { - PluginCore.WriteToChat($"[NavRoute] ERROR: D3DService is null!"); + PluginCore.WriteToChat($"Navigation: 3D service unavailable"); return; } // Limit the number of lines to prevent lag int maxLines = Math.Min(waypoints.Count - 1, 500); // Max 500 lines - PluginCore.WriteToChat($"[NavRoute] Creating {maxLines} navigation lines from {waypoints.Count} waypoints..."); - int linesCreated = 0; for (int i = 1; i <= maxLines; i++) { var current = waypoints[i]; var previous = waypoints[i - 1]; - - PluginCore.WriteToChat($"[NavRoute] Creating line {i}: From ({previous.NS:F2}, {previous.EW:F2}, {previous.Z:F2}) to ({current.NS:F2}, {current.EW:F2}, {current.Z:F2})"); if (CreateLineBetweenWaypoints(previous, current)) { @@ -363,18 +324,14 @@ namespace MosswartMassacre } } - PluginCore.WriteToChat($"[NavRoute] Successfully created {linesCreated} D3D line objects out of {maxLines} attempted"); - PluginCore.WriteToChat($"[NavRoute] Total D3D objects in list: {lineObjects.Count}"); - if (waypoints.Count > 501) { - PluginCore.WriteToChat($"[NavRoute] Route has {waypoints.Count} waypoints, showing first {maxLines} segments"); + PluginCore.WriteToChat($"Navigation: Large route - showing {maxLines} of {waypoints.Count} segments"); } } catch (Exception ex) { - PluginCore.WriteToChat($"[NavRoute] Error creating line objects: {ex.Message}"); - PluginCore.WriteToChat($"[NavRoute] Stack trace: {ex.StackTrace}"); + PluginCore.WriteToChat($"Navigation: Error creating visualization - {ex.Message}"); } } @@ -389,34 +346,20 @@ namespace MosswartMassacre Math.Pow((to.Z - from.Z) * 240, 2) ); - if (distance <= 0) - { - PluginCore.WriteToChat($"[NavRoute] Skipping line with zero distance"); - return false; - } - - PluginCore.WriteToChat($"[NavRoute] Creating D3D line object with distance: {distance:F2}"); + if (distance <= 0) return false; // Create D3D line object var lineObj = CoreManager.Current.D3DService.NewD3DObj(); - if (lineObj == null) - { - PluginCore.WriteToChat($"[NavRoute] ERROR: Failed to create D3D object!"); - return false; - } - - PluginCore.WriteToChat($"[NavRoute] D3D object created successfully"); + if (lineObj == null) return false; lineObj.SetShape(D3DShape.Cube); lineObj.Color = routeColor.ToArgb(); - PluginCore.WriteToChat($"[NavRoute] Set shape and color (ARGB: {routeColor.ToArgb()})"); // Position at midpoint between waypoints float midNS = (float)(from.NS + to.NS) / 2; float midEW = (float)(from.EW + to.EW) / 2; float midZ = (float)((from.Z + to.Z) * 120) + 0.1f; // Slightly higher than UtilityBelt - PluginCore.WriteToChat($"[NavRoute] Anchoring at: NS={midNS:F2}, EW={midEW:F2}, Z={midZ:F2}"); lineObj.Anchor(midNS, midEW, midZ); // Orient toward destination @@ -424,28 +367,20 @@ namespace MosswartMassacre float orientEW = (float)from.EW; float orientZ = (float)(from.Z * 240) + 0.1f; - PluginCore.WriteToChat($"[NavRoute] Orienting to: NS={orientNS:F2}, EW={orientEW:F2}, Z={orientZ:F2}"); lineObj.OrientToCoords(orientNS, orientEW, orientZ, true); // Scale to create line effect lineObj.ScaleX = 0.3f; // Slightly thicker than UtilityBelt lineObj.ScaleZ = 0.3f; lineObj.ScaleY = (float)distance; - - PluginCore.WriteToChat($"[NavRoute] Set scale: X={lineObj.ScaleX}, Y={lineObj.ScaleY:F2}, Z={lineObj.ScaleZ}"); lineObj.Visible = true; - PluginCore.WriteToChat($"[NavRoute] Set visible to true"); - lineObjects.Add(lineObj); - PluginCore.WriteToChat($"[NavRoute] Added line object to list (total: {lineObjects.Count})"); return true; } - catch (Exception ex) + catch { - PluginCore.WriteToChat($"[NavRoute] Error creating line: {ex.Message}"); - PluginCore.WriteToChat($"[NavRoute] Stack trace: {ex.StackTrace}"); return false; } } diff --git a/MosswartMassacre/NavVisualization.cs b/MosswartMassacre/NavVisualization.cs index 3180d56..824462f 100644 --- a/MosswartMassacre/NavVisualization.cs +++ b/MosswartMassacre/NavVisualization.cs @@ -39,7 +39,6 @@ namespace MosswartMassacre if (!string.IsNullOrEmpty(PluginSettings.Instance?.VTankProfilesPath)) { vtankProfilesDirectory = PluginSettings.Instance.VTankProfilesPath; - PluginCore.WriteToChat($"[NavViz] Using configured VTank profiles path: {vtankProfilesDirectory}"); return; } @@ -54,20 +53,17 @@ namespace MosswartMassacre if (!string.IsNullOrEmpty(profilePath)) { vtankProfilesDirectory = profilePath; - PluginCore.WriteToChat($"[NavViz] Found VTank profiles from registry: {vtankProfilesDirectory}"); return; } } } - catch (Exception regEx) + catch { - PluginCore.WriteToChat($"[NavViz] Registry lookup failed: {regEx.Message}"); } // Fall back to default path vtankProfilesDirectory = defaultPath; - PluginCore.WriteToChat($"[NavViz] Using default VTank path: {vtankProfilesDirectory}"); - PluginCore.WriteToChat($"[NavViz] If this is wrong, configure the correct path in Settings tab."); + // Using default path - user can configure in Settings if needed } catch (Exception ex) { @@ -76,6 +72,10 @@ namespace MosswartMassacre } } + /// + /// Scan VTank directory for .nav files and populate available routes list + /// Filters out follow files and temporary files, sorts alphabetically + /// public void RefreshNavFileList() { // Re-initialize directory in case settings changed @@ -83,43 +83,26 @@ namespace MosswartMassacre availableNavFiles.Clear(); - PluginCore.WriteToChat($"[NavViz] Refreshing nav files from: {vtankProfilesDirectory}"); if (string.IsNullOrEmpty(vtankProfilesDirectory)) { - PluginCore.WriteToChat("[NavViz] No VTank directory set"); + PluginCore.WriteToChat("VTank directory not configured. Set path in Settings tab."); return; } if (!Directory.Exists(vtankProfilesDirectory)) { - PluginCore.WriteToChat($"[NavViz] Directory does not exist: {vtankProfilesDirectory}"); + PluginCore.WriteToChat($"VTank directory not found: {vtankProfilesDirectory}"); return; } try { - // Get ALL files first for debugging + // Get all files and filter for .nav files only, excluding follow/temporary files var allFiles = Directory.GetFiles(vtankProfilesDirectory); - PluginCore.WriteToChat($"[NavViz] Directory contents ({allFiles.Length} files):"); - foreach (var file in allFiles.Take(10)) // Show first 10 files - { - PluginCore.WriteToChat($" - {Path.GetFileName(file)}"); - } - - // Filter for .nav files ONLY and exclude follow files var navFiles = allFiles - .Where(file => { - var ext = Path.GetExtension(file); - var isNav = ext.Equals(".nav", StringComparison.OrdinalIgnoreCase); - PluginCore.WriteToChat($"[NavViz] File: {Path.GetFileName(file)} - Extension: '{ext}' - IsNav: {isNav}"); - return isNav; - }) - .Select(file => { - var name = Path.GetFileNameWithoutExtension(file); - PluginCore.WriteToChat($"[NavViz] Nav file name: {name}"); - return name; - }) + .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)) @@ -128,14 +111,24 @@ namespace MosswartMassacre availableNavFiles.AddRange(navFiles); - PluginCore.WriteToChat($"[NavViz] Found {navFiles.Count} .nav files: {string.Join(", ", 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($"[NavViz] Error refreshing nav files: {ex.Message}"); + PluginCore.WriteToChat($"Navigation: Error scanning files - {ex.Message}"); } } + /// + /// Load a specific navigation route file for visualization + /// Clears current route if "None" specified, otherwise loads .nav file + /// + /// Name of .nav file (without extension) or "None" + /// True if route loaded successfully, false otherwise public bool LoadRoute(string navFileName) { try @@ -149,7 +142,6 @@ namespace MosswartMassacre if (string.IsNullOrEmpty(navFileName) || navFileName == "None") { - PluginCore.WriteToChat("[NavViz] Route cleared"); RouteChanged?.Invoke(this, EventArgs.Empty); return true; } @@ -158,7 +150,7 @@ namespace MosswartMassacre if (!File.Exists(fullPath)) { - PluginCore.WriteToChat($"[NavViz] Nav file not found: {navFileName}"); + PluginCore.WriteToChat($"Navigation file '{navFileName}' not found"); return false; } @@ -172,41 +164,35 @@ namespace MosswartMassacre } // Show route if visualization is enabled - PluginCore.WriteToChat($"[NavViz] LoadRoute: IsEnabled = {IsEnabled}"); if (IsEnabled) { - PluginCore.WriteToChat($"[NavViz] Calling Show() for route {navFileName}"); currentRoute.Show(); } - else - { - PluginCore.WriteToChat($"[NavViz] Visualization disabled, not showing route"); - } RouteChanged?.Invoke(this, EventArgs.Empty); return true; } catch (Exception ex) { - PluginCore.WriteToChat($"[NavViz] Error loading route {navFileName}: {ex.Message}"); + PluginCore.WriteToChat($"Navigation: Failed to load '{navFileName}' - {ex.Message}"); return false; } } + /// + /// Enable or disable navigation route visualization in 3D world + /// Shows/hides the currently loaded route based on enabled state + /// + /// True to show route lines, false to hide public void SetEnabled(bool enabled) { - PluginCore.WriteToChat($"[NavViz] SetEnabled called: current={IsEnabled}, new={enabled}"); - if (IsEnabled == enabled) - { - PluginCore.WriteToChat($"[NavViz] SetEnabled: no change needed"); - return; - } + // No change needed if already in desired state + if (IsEnabled == enabled) return; IsEnabled = enabled; if (currentRoute != null) { - PluginCore.WriteToChat($"[NavViz] SetEnabled: currentRoute exists, {(enabled ? "showing" : "hiding")}"); if (enabled) { currentRoute.Show(); @@ -218,10 +204,9 @@ namespace MosswartMassacre } else { - PluginCore.WriteToChat($"[NavViz] SetEnabled: no currentRoute to {(enabled ? "show" : "hide")}"); } - PluginCore.WriteToChat($"[NavViz] Navigation visualization {(enabled ? "enabled" : "disabled")}"); + PluginCore.WriteToChat($"Navigation visualization {(enabled ? "enabled" : "disabled")}"); } public void ToggleEnabled() diff --git a/MosswartMassacre/PluginCore.cs b/MosswartMassacre/PluginCore.cs index aa05bbb..cacdeeb 100644 --- a/MosswartMassacre/PluginCore.cs +++ b/MosswartMassacre/PluginCore.cs @@ -28,6 +28,45 @@ namespace MosswartMassacre internal static DateTime statsStartTime = DateTime.Now; internal static Timer updateTimer; public static bool RareMetaEnabled { get; set; } = true; + + // VVS View Management + private static class ViewManager + { + public static void ViewInit() + { + Views.VVSTabbedMainView.ViewInit(); + } + + public static void ViewDestroy() + { + Views.VVSTabbedMainView.ViewDestroy(); + } + + public static void UpdateKillStats(int totalKills, double killsPer5Min, double killsPerHour) + { + Views.VVSTabbedMainView.UpdateKillStats(totalKills, killsPer5Min, killsPerHour); + } + + public static void UpdateElapsedTime(TimeSpan elapsed) + { + Views.VVSTabbedMainView.UpdateElapsedTime(elapsed); + } + + public static void UpdateRareCount(int rareCount) + { + Views.VVSTabbedMainView.UpdateRareCount(rareCount); + } + + public static void SetRareMetaToggleState(bool enabled) + { + Views.VVSTabbedMainView.SetRareMetaToggleState(enabled); + } + + public static void RefreshSettingsFromConfig() + { + Views.VVSTabbedMainView.RefreshSettingsFromConfig(); + } + } public static bool RemoteCommandsEnabled { get; set; } = false; public static bool HttpServerEnabled { get; set; } = false; public static string CharTag { get; set; } = ""; @@ -63,7 +102,7 @@ namespace MosswartMassacre updateTimer.Start(); // Initialize the view (UI) - use tabbed interface by default - TabbedMainView.ViewInit(); + ViewManager.ViewInit(); // Enable TLS1.2 ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls12; @@ -113,7 +152,7 @@ namespace MosswartMassacre } // Clean up the view - TabbedMainView.ViewDestroy(); + ViewManager.ViewDestroy(); //Disable vtank interface vTank.Disable(); // sluta lyssna på commands @@ -149,8 +188,8 @@ namespace MosswartMassacre HttpServerEnabled = PluginSettings.Instance.HttpServerEnabled; TelemetryEnabled = PluginSettings.Instance.TelemetryEnabled; CharTag = PluginSettings.Instance.CharTag; - TabbedMainView.SetRareMetaToggleState(RareMetaEnabled); - TabbedMainView.RefreshSettingsFromConfig(); // Refresh all UI settings after loading + ViewManager.SetRareMetaToggleState(RareMetaEnabled); + ViewManager.RefreshSettingsFromConfig(); // Refresh all UI settings after loading if (TelemetryEnabled) Telemetry.Start(); if (WebSocketEnabled) @@ -238,13 +277,13 @@ namespace MosswartMassacre totalKills++; lastKillTime = DateTime.Now; CalculateKillsPerInterval(); - TabbedMainView.UpdateKillStats(totalKills, killsPer5Min, killsPerHour); + ViewManager.UpdateKillStats(totalKills, killsPer5Min, killsPerHour); } if (IsRareDiscoveryMessage(e.Text, out string rareText)) { rareCount++; - TabbedMainView.UpdateRareCount(rareCount); + ViewManager.UpdateRareCount(rareCount); if (RareMetaEnabled) { @@ -324,11 +363,11 @@ namespace MosswartMassacre { // Update the elapsed time TimeSpan elapsed = DateTime.Now - statsStartTime; - TabbedMainView.UpdateElapsedTime(elapsed); + ViewManager.UpdateElapsedTime(elapsed); // Recalculate kill rates CalculateKillsPerInterval(); - TabbedMainView.UpdateKillStats(totalKills, killsPer5Min, killsPerHour); + ViewManager.UpdateKillStats(totalKills, killsPer5Min, killsPerHour); } catch (Exception ex) { @@ -426,14 +465,14 @@ namespace MosswartMassacre killsPerHour = 0; WriteToChat("Stats have been reset."); - TabbedMainView.UpdateKillStats(totalKills, killsPer5Min, killsPerHour); - TabbedMainView.UpdateRareCount(rareCount); + ViewManager.UpdateKillStats(totalKills, killsPer5Min, killsPerHour); + ViewManager.UpdateRareCount(rareCount); } public static void ToggleRareMeta() { PluginSettings.Instance.RareMetaEnabled = !PluginSettings.Instance.RareMetaEnabled; RareMetaEnabled = PluginSettings.Instance.RareMetaEnabled; - TabbedMainView.SetRareMetaToggleState(RareMetaEnabled); + ViewManager.SetRareMetaToggleState(RareMetaEnabled); } [DllImport("Decal.dll")] @@ -563,7 +602,7 @@ namespace MosswartMassacre case "meta": RareMetaEnabled = !RareMetaEnabled; WriteToChat($"Rare meta state is now {(RareMetaEnabled ? "ON" : "OFF")}"); - TabbedMainView.SetRareMetaToggleState(RareMetaEnabled); // <-- sync the UI + ViewManager.SetRareMetaToggleState(RareMetaEnabled); // <-- sync the UI break; case "http": diff --git a/MosswartMassacre/Properties/AssemblyInfo.cs b/MosswartMassacre/Properties/AssemblyInfo.cs index e084d4c..b7482f9 100644 --- a/MosswartMassacre/Properties/AssemblyInfo.cs +++ b/MosswartMassacre/Properties/AssemblyInfo.cs @@ -26,5 +26,5 @@ using System.Runtime.InteropServices; // Minor Version // Build Number // Revision -[assembly: AssemblyVersion("3.0.0.6")] -[assembly: AssemblyFileVersion("3.0.0.6")] \ No newline at end of file +[assembly: AssemblyVersion("3.0.1.0")] +[assembly: AssemblyFileVersion("3.0.1.0")] \ No newline at end of file diff --git a/MosswartMassacre/ViewSystemSelector.cs b/MosswartMassacre/ViewSystemSelector.cs deleted file mode 100644 index 5e75b7a..0000000 --- a/MosswartMassacre/ViewSystemSelector.cs +++ /dev/null @@ -1,262 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -//File: ViewSystemSelector.cs -// -//Description: Contains the MyClasses.MetaViewWrappers.ViewSystemSelector class, -// which is used to determine whether the Virindi View Service is enabled. -// As with all the VVS wrappers, the VVS_REFERENCED compilation symbol must be -// defined for the VVS code to be compiled. Otherwise, only Decal views are used. -// -//References required: -// VirindiViewService (if VVS_REFERENCED is defined) -// Decal.Adapter -// Decal.Interop.Core -// -//This file is Copyright (c) 2009 VirindiPlugins -// -//Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -//The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -/////////////////////////////////////////////////////////////////////////////// - -using System; -using System.Collections.Generic; -using System.Text; -using System.Reflection; - -#if METAVIEW_PUBLIC_NS -namespace MetaViewWrappers -#else -namespace MyClasses.MetaViewWrappers -#endif -{ - internal static class ViewSystemSelector - { - public enum eViewSystem - { - DecalInject, - VirindiViewService, - } - - - ///////////////////////////////System presence detection/////////////////////////////// - - public static bool IsPresent(Decal.Adapter.Wrappers.PluginHost pHost, eViewSystem VSystem) - { - switch (VSystem) - { - case eViewSystem.DecalInject: - return true; - case eViewSystem.VirindiViewService: - return VirindiViewsPresent(pHost); - default: - return false; - } - } - static bool VirindiViewsPresent(Decal.Adapter.Wrappers.PluginHost pHost) - { -#if VVS_REFERENCED - System.Reflection.Assembly[] asms = AppDomain.CurrentDomain.GetAssemblies(); - - foreach (System.Reflection.Assembly a in asms) - { - AssemblyName nmm = a.GetName(); - if ((nmm.Name == "VirindiViewService") && (nmm.Version >= new System.Version("1.0.0.37"))) - { - try - { - return Curtain_VVS_Running(); - } - catch - { - return false; - } - } - } - - return false; -#else - return false; -#endif - } - public static bool VirindiViewsPresent(Decal.Adapter.Wrappers.PluginHost pHost, Version minver) - { -#if VVS_REFERENCED - System.Reflection.Assembly[] asms = AppDomain.CurrentDomain.GetAssemblies(); - - foreach (System.Reflection.Assembly a in asms) - { - AssemblyName nm = a.GetName(); - if ((nm.Name == "VirindiViewService") && (nm.Version >= minver)) - { - try - { - return Curtain_VVS_Running(); - } - catch - { - return false; - } - } - } - - return false; -#else - return false; -#endif - } - -#if VVS_REFERENCED - static bool Curtain_VVS_Running() - { - return VirindiViewService.Service.Running; - } -#endif - - ///////////////////////////////CreateViewResource/////////////////////////////// - - public static IView CreateViewResource(Decal.Adapter.Wrappers.PluginHost pHost, string pXMLResource) - { -#if VVS_REFERENCED - if (IsPresent(pHost, eViewSystem.VirindiViewService)) - return CreateViewResource(pHost, pXMLResource, eViewSystem.VirindiViewService); - else -#endif - return CreateViewResource(pHost, pXMLResource, eViewSystem.DecalInject); - } - public static IView CreateViewResource(Decal.Adapter.Wrappers.PluginHost pHost, string pXMLResource, eViewSystem VSystem) - { - if (!IsPresent(pHost, VSystem)) return null; - switch (VSystem) - { - case eViewSystem.DecalInject: - return CreateDecalViewResource(pHost, pXMLResource); - case eViewSystem.VirindiViewService: -#if VVS_REFERENCED - return CreateMyHudViewResource(pHost, pXMLResource); -#else - break; -#endif - } - return null; - } - static IView CreateDecalViewResource(Decal.Adapter.Wrappers.PluginHost pHost, string pXMLResource) - { - IView ret = new DecalControls.View(); - ret.Initialize(pHost, pXMLResource); - return ret; - } - -#if VVS_REFERENCED - static IView CreateMyHudViewResource(Decal.Adapter.Wrappers.PluginHost pHost, string pXMLResource) - { - IView ret = new VirindiViewServiceHudControls.View(); - ret.Initialize(pHost, pXMLResource); - return ret; - } -#endif - - - ///////////////////////////////CreateViewXML/////////////////////////////// - - public static IView CreateViewXML(Decal.Adapter.Wrappers.PluginHost pHost, string pXML) - { -#if VVS_REFERENCED - if (IsPresent(pHost, eViewSystem.VirindiViewService)) - return CreateViewXML(pHost, pXML, eViewSystem.VirindiViewService); - else -#endif - return CreateViewXML(pHost, pXML, eViewSystem.DecalInject); - } - - public static IView CreateViewXML(Decal.Adapter.Wrappers.PluginHost pHost, string pXML, eViewSystem VSystem) - { - if (!IsPresent(pHost, VSystem)) return null; - switch (VSystem) - { - case eViewSystem.DecalInject: - return CreateDecalViewXML(pHost, pXML); - case eViewSystem.VirindiViewService: -#if VVS_REFERENCED - return CreateMyHudViewXML(pHost, pXML); -#else - break; -#endif - } - return null; - } - static IView CreateDecalViewXML(Decal.Adapter.Wrappers.PluginHost pHost, string pXML) - { - IView ret = new DecalControls.View(); - ret.InitializeRawXML(pHost, pXML); - return ret; - } - -#if VVS_REFERENCED - static IView CreateMyHudViewXML(Decal.Adapter.Wrappers.PluginHost pHost, string pXML) - { - IView ret = new VirindiViewServiceHudControls.View(); - ret.InitializeRawXML(pHost, pXML); - return ret; - } -#endif - - - ///////////////////////////////HasChatOpen/////////////////////////////// - - public static bool AnySystemHasChatOpen(Decal.Adapter.Wrappers.PluginHost pHost) - { - if (IsPresent(pHost, eViewSystem.VirindiViewService)) - if (HasChatOpen_VirindiViews()) return true; - if (pHost.Actions.ChatState) return true; - return false; - } - - static bool HasChatOpen_VirindiViews() - { -#if VVS_REFERENCED - if (VirindiViewService.HudView.FocusControl != null) - { - if (VirindiViewService.HudView.FocusControl.GetType() == typeof(VirindiViewService.Controls.HudTextBox)) - return true; - } - return false; -#else - return false; -#endif - } - - public delegate void delConditionalSplit(object data); - public static void ViewConditionalSplit(IView v, delConditionalSplit onDecal, delConditionalSplit onVVS, object data) - { - Type vtype = v.GetType(); - -#if VVS_REFERENCED - if (vtype == typeof(VirindiViewServiceHudControls.View)) - { - if (onVVS != null) - onVVS(data); - } -#endif - - if (vtype == typeof(DecalControls.View)) - { - if (onDecal != null) - onDecal(data); - } - } - } -} diff --git a/MosswartMassacre/ViewXML/mainViewTabbed.xml b/MosswartMassacre/ViewXML/mainViewTabbed.xml index 22303ae..2ce4ff4 100644 --- a/MosswartMassacre/ViewXML/mainViewTabbed.xml +++ b/MosswartMassacre/ViewXML/mainViewTabbed.xml @@ -25,19 +25,19 @@ - + - + - + - + - + @@ -46,7 +46,7 @@ - + @@ -90,10 +90,10 @@ - + - + @@ -101,14 +101,14 @@ - + - + - - + + diff --git a/MosswartMassacre/Views/BaseView.cs b/MosswartMassacre/Views/BaseView.cs deleted file mode 100644 index 2020be7..0000000 --- a/MosswartMassacre/Views/BaseView.cs +++ /dev/null @@ -1,177 +0,0 @@ -using System; -using System.Drawing; -using System.IO; -using System.Runtime.InteropServices; -using MyClasses.MetaViewWrappers; - -namespace MosswartMassacre.Views -{ - public class BaseView : IDisposable - { - #region Windows API for boundary checking - [StructLayout(LayoutKind.Sequential)] - public struct RECT - { - public int Left; - public int Top; - public int Right; - public int Bottom; - - public int Width { get { return Right - Left; } } - public int Height { get { return Bottom - Top; } } - } - - [DllImport("user32.dll", SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool GetWindowRect(IntPtr hWnd, ref RECT lpRect); - #endregion - - internal IView view; - protected PluginCore pluginCore; - - public BaseView(PluginCore core) - { - pluginCore = core; - } - - protected void CreateFromXMLResource(string resourcePath) - { - try - { - view = ViewSystemSelector.CreateViewResource(PluginCore.MyHost, resourcePath); - // Note: IView doesn't have VisibleChanged event, so we'll check bounds manually when needed - } - catch (Exception ex) - { - PluginCore.WriteToChat($"Error creating view from {resourcePath}: {ex.Message}"); - } - } - - protected void KeepWindowInBounds() - { - try - { - RECT rect = new RECT(); - IntPtr gameWindowHandle = PluginCore.MyHost?.Decal?.Hwnd ?? IntPtr.Zero; - - if (gameWindowHandle != IntPtr.Zero && GetWindowRect(gameWindowHandle, ref rect)) - { - Point currentLocation = view.Location; - Size viewSize = view.Size; - - // Check if window is outside right boundary - if (currentLocation.X + viewSize.Width > rect.Width) - { - currentLocation.X = rect.Width - viewSize.Width; - } - // Check if window is outside left boundary - else if (currentLocation.X < 0) - { - currentLocation.X = 20; - } - - // Check if window is outside bottom boundary - if (currentLocation.Y + viewSize.Height > rect.Height) - { - currentLocation.Y = rect.Height - viewSize.Height; - } - // Check if window is outside top boundary - else if (currentLocation.Y < 0) - { - currentLocation.Y = 20; - } - - // Only update location if it changed - if (currentLocation != view.Location) - { - view.Location = currentLocation; - } - } - } - catch - { - // Don't spam chat with boundary check errors, just log silently - } - } - - protected virtual void SaveWindowPosition() - { - // Override in derived classes to save position to settings - } - - protected virtual void RestoreWindowPosition() - { - // Override in derived classes to restore position from settings - } - - public virtual void Initialize() - { - try - { - RestoreWindowPosition(); - } - catch (Exception ex) - { - PluginCore.WriteToChat($"Error initializing view: {ex.Message}"); - } - } - - public virtual void Show() - { - if (view != null) - { - view.Visible = true; - } - } - - public virtual void Hide() - { - if (view != null) - { - view.Visible = false; - } - } - - public virtual void Toggle() - { - if (view != null) - { - view.Visible = !view.Visible; - } - } - - #region IDisposable Support - private bool disposedValue = false; - - protected virtual void Dispose(bool disposing) - { - if (!disposedValue) - { - if (disposing) - { - try - { - SaveWindowPosition(); - - if (view != null) - { - view.Dispose(); - } - view = null; - } - catch (Exception ex) - { - PluginCore.WriteToChat($"Error disposing view: {ex.Message}"); - } - } - disposedValue = true; - } - } - - public void Dispose() - { - Dispose(true); - } - #endregion - } -} \ No newline at end of file diff --git a/MosswartMassacre/Views/TabbedMainView.cs b/MosswartMassacre/Views/TabbedMainView.cs deleted file mode 100644 index 29f429f..0000000 --- a/MosswartMassacre/Views/TabbedMainView.cs +++ /dev/null @@ -1,794 +0,0 @@ -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); - } - } - } -} \ No newline at end of file diff --git a/MosswartMassacre/Views/VVSBaseView.cs b/MosswartMassacre/Views/VVSBaseView.cs new file mode 100644 index 0000000..e5adc2d --- /dev/null +++ b/MosswartMassacre/Views/VVSBaseView.cs @@ -0,0 +1,395 @@ +using System; +using System.Drawing; +using System.Runtime.InteropServices; +using System.Timers; +using VirindiViewService; +using VirindiViewService.XMLParsers; + +namespace MosswartMassacre.Views +{ + /// + /// Base class for VVS (VirindiViewService) based views. + /// Replaces the wrapper-based BaseView with direct VVS integration. + /// + public class VVSBaseView : IDisposable + { + #region Windows API for boundary checking + [StructLayout(LayoutKind.Sequential)] + public struct RECT + { + public int Left; + public int Top; + public int Right; + public int Bottom; + + public int Width { get { return Right - Left; } } + public int Height { get { return Bottom - Top; } } + } + + [DllImport("user32.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool GetWindowRect(IntPtr hWnd, ref RECT lpRect); + #endregion + + #region Core VVS Components + protected HudView view; + protected ViewProperties properties; + protected ControlGroup controls; + protected PluginCore pluginCore; + #endregion + + #region Position Management + private Timer positionSaveTimer; + #endregion + + public VVSBaseView(PluginCore core) + { + pluginCore = core; + InitializePositionTimer(); + } + + #region VVS Initialization + protected void CreateFromXMLResource(string resourcePath, bool doIcon = true, bool doTitle = true) + { + try + { + // Parse XML using VVS Decal3XMLParser + new Decal3XMLParser().ParseFromResource(resourcePath, out properties, out controls); + + // Set window properties + if (doTitle) + { + properties.Title = "Mosswart Massacre v3.0"; + } + + if (doIcon) + { + // Use default icon for now - can be customized later + properties.Icon = 7735; // Same icon as in XML + } + + // Create the HudView + view = new HudView(properties, controls); + + // Subscribe to essential events + view.VisibleChanged += View_VisibleChanged; + view.Moved += View_Moved; + } + catch (Exception ex) + { + PluginCore.WriteToChat($"Error creating VVS view from {resourcePath}: {ex.Message}"); + PluginCore.WriteToChat($"Stack trace: {ex.StackTrace}"); + } + } + + protected void CreateFromXMLString(string xmlString, bool doIcon = true, bool doTitle = true) + { + try + { + // Parse XML string using VVS Decal3XMLParser + new Decal3XMLParser().Parse(xmlString, out properties, out controls); + + if (doTitle) + { + properties.Title = "Mosswart Massacre v3.0"; + } + + if (doIcon) + { + properties.Icon = 7735; + } + + view = new HudView(properties, controls); + view.VisibleChanged += View_VisibleChanged; + view.Moved += View_Moved; + } + catch (Exception ex) + { + PluginCore.WriteToChat($"Error creating VVS view from XML string: {ex.Message}"); + } + } + #endregion + + #region Control Access + /// + /// Get a control by name with proper type casting. + /// Usage: var button = GetControl<HudButton>("btnExample"); + /// + protected T GetControl(string controlName) where T : class + { + try + { + if (view != null && view[controlName] != null) + { + return view[controlName] as T; + } + return null; + } + catch (Exception ex) + { + PluginCore.WriteToChat($"Error getting control '{controlName}': {ex.Message}"); + return null; + } + } + + /// + /// Get a control by name (alternative syntax) + /// Usage: var button = (HudButton)GetControl("btnExample"); + /// + protected object GetControl(string controlName) + { + try + { + return view?[controlName]; + } + catch (Exception ex) + { + PluginCore.WriteToChat($"Error getting control '{controlName}': {ex.Message}"); + return null; + } + } + #endregion + + #region Window Management + protected virtual 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 virtual 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}"); + } + } + + protected void KeepWindowInBounds() + { + try + { + if (view == null) return; + + RECT rect = new RECT(); + IntPtr gameWindowHandle = PluginCore.MyHost?.Decal?.Hwnd ?? IntPtr.Zero; + + if (gameWindowHandle != IntPtr.Zero && GetWindowRect(gameWindowHandle, ref rect)) + { + Point currentLocation = view.Location; + int viewWidth = view.Width; + int viewHeight = view.Height; + + bool needsUpdate = false; + + // Check right boundary + if (currentLocation.X + viewWidth > rect.Width) + { + currentLocation.X = rect.Width - viewWidth; + needsUpdate = true; + } + // Check left boundary + else if (currentLocation.X < 0) + { + currentLocation.X = 20; + needsUpdate = true; + } + + // Check bottom boundary + if (currentLocation.Y + viewHeight > rect.Height) + { + currentLocation.Y = rect.Height - viewHeight; + needsUpdate = true; + } + // Check top boundary + else if (currentLocation.Y < 0) + { + currentLocation.Y = 20; + needsUpdate = true; + } + + if (needsUpdate) + { + view.Location = currentLocation; + } + } + } + catch + { + // Silently ignore boundary check errors + } + } + #endregion + + #region Position Timer Management + private void InitializePositionTimer() + { + positionSaveTimer = new Timer(2000); // 2 second delay after movement stops + positionSaveTimer.Elapsed += (s, e) => { + SaveWindowPosition(); + positionSaveTimer.Stop(); + }; + } + + private void View_Moved(object sender, EventArgs e) + { + try + { + // Reset timer when window moves + if (positionSaveTimer != null) + { + if (positionSaveTimer.Enabled) + positionSaveTimer.Stop(); + + positionSaveTimer.Start(); + } + } + catch + { + // Ignore timer errors + } + } + + private void View_VisibleChanged(object sender, EventArgs e) + { + try + { + if (view.Visible) + { + KeepWindowInBounds(); + } + } + catch + { + // Ignore visibility change errors + } + } + #endregion + + #region Public Interface + public virtual void Initialize() + { + try + { + RestoreWindowPosition(); + KeepWindowInBounds(); + } + catch (Exception ex) + { + PluginCore.WriteToChat($"Error initializing VVS view: {ex.Message}"); + } + } + + public virtual void Show() + { + if (view != null) + { + view.Visible = true; + } + } + + public virtual void Hide() + { + if (view != null) + { + view.Visible = false; + } + } + + public virtual void Toggle() + { + if (view != null) + { + view.Visible = !view.Visible; + } + } + + public bool IsVisible + { + get { return view?.Visible ?? false; } + } + + public Point Location + { + get { return view?.Location ?? Point.Empty; } + set { if (view != null) view.Location = value; } + } + + public Size Size + { + get { return view != null ? new Size(view.Width, view.Height) : Size.Empty; } + } + #endregion + + #region IDisposable Support + private bool disposedValue = false; + + protected virtual void Dispose(bool disposing) + { + if (!disposedValue) + { + if (disposing) + { + try + { + // Save final position before disposal + SaveWindowPosition(); + + // Clean up timers + if (positionSaveTimer != null) + { + positionSaveTimer.Stop(); + positionSaveTimer.Dispose(); + positionSaveTimer = null; + } + + // Clean up VVS view + if (view != null) + { + view.VisibleChanged -= View_VisibleChanged; + view.Moved -= View_Moved; + view.Dispose(); + view = null; + } + + // Clean up VVS objects + properties = null; + controls = null; + } + catch (Exception ex) + { + PluginCore.WriteToChat($"Error disposing VVS view: {ex.Message}"); + } + } + disposedValue = true; + } + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + #endregion + } +} \ No newline at end of file diff --git a/MosswartMassacre/Views/VVSTabbedMainView.cs b/MosswartMassacre/Views/VVSTabbedMainView.cs new file mode 100644 index 0000000..0c13665 --- /dev/null +++ b/MosswartMassacre/Views/VVSTabbedMainView.cs @@ -0,0 +1,845 @@ +using System; +using System.Drawing; +using System.Timers; +using VirindiViewService.Controls; + +namespace MosswartMassacre.Views +{ + /// + /// VVS-based tabbed main view - direct VirindiViewService integration. + /// Replaces wrapper-based TabbedMainView with modern VVS controls. + /// + internal class VVSTabbedMainView : VVSBaseView + { + private static VVSTabbedMainView instance; + + #region Main Tab Controls + private HudStaticText lblTotalKills; + private HudStaticText lblKillsPer5Min; + private HudStaticText lblKillsPerHour; + private HudStaticText lblElapsedTime; + private HudStaticText lblRareCount; + private HudStaticText lblAutoLootRare; + private HudStaticText lblStatus; + private HudStaticText lblWebSocketStatus; + #endregion + + #region Settings Tab Controls + private HudCheckBox chkRareMetaEnabled; + private HudCheckBox chkRemoteCommandsEnabled; + private HudCheckBox chkHttpServerEnabled; + private HudCheckBox chkWebSocketEnabled; + private HudCheckBox chkTelemetryEnabled; + private HudTextBox txtCharTag; + private HudTextBox txtVTankPath; + #endregion + + #region Statistics Tab Controls + private HudStaticText lblDetailedKillsValue; + private HudStaticText lblBestHourValue; + private HudStaticText lblAverageKillsValue; + private HudStaticText lblRareStatsValue; + private HudStaticText lblRareRateValue; + private HudStaticText lblSessionTimeValue; + private HudStaticText lblLastKillValue; + private HudButton btnResetStats; + #endregion + + #region Navigation Tab Controls (Basic) + private HudCheckBox chkNavVisualizationEnabled; + private HudCombo cmbNavFiles; + private HudButton btnRefreshNavFiles; + private HudStaticText lblNavStatus; + private HudButton btnLoadRoute; + private HudButton btnClearRoute; + #endregion + + #region Statistics Tracking + private double bestHourlyKills = 0; + private DateTime sessionStartTime; + #endregion + + public VVSTabbedMainView(PluginCore core) : base(core) + { + instance = this; + sessionStartTime = DateTime.Now; + } + + #region Static Interface Methods + public static void ViewInit() + { + try + { + if (instance == null) + { + instance = new VVSTabbedMainView(null); + } + instance.InitializeView(); + } + catch (Exception ex) + { + PluginCore.WriteToChat("Error initializing VVS tabbed view: " + ex.Message); + } + } + + public static void ViewDestroy() + { + try + { + if (instance != null) + { + instance.Dispose(); + instance = null; + } + } + catch (Exception ex) + { + PluginCore.WriteToChat("Error destroying VVS tabbed view: " + ex.Message); + } + } + #endregion + + #region Initialization + private void InitializeView() + { + try + { + // Create view from working original XML layout + CreateFromXMLResource("MosswartMassacre.ViewXML.mainViewTabbed.xml"); + + // Initialize all tab controls + InitializeMainTabControls(); + InitializeSettingsTabControls(); + InitializeStatisticsTabControls(); + InitializeNavigationTabControls(); + + // Initialize the base view and set initial position + Initialize(); + + // Make the view visible and show in plugin bar + if (view != null) + { + view.Visible = true; + view.ShowInBar = true; + } + } + catch (Exception ex) + { + PluginCore.WriteToChat("Error in VVS InitializeView: " + ex.Message); + } + } + + private void InitializeMainTabControls() + { + try + { + // Main tab - existing functionality using VVS controls + lblTotalKills = GetControl("lblTotalKills"); + lblKillsPer5Min = GetControl("lblKillsPer5Min"); + lblKillsPerHour = GetControl("lblKillsPerHour"); + lblElapsedTime = GetControl("lblElapsedTime"); + lblRareCount = GetControl("lblRareCount"); + lblAutoLootRare = GetControl("lblAutoLootRare"); + lblStatus = GetControl("lblStatus"); + lblWebSocketStatus = GetControl("lblWebSocketStatus"); + + // Update status displays immediately + UpdateStatus(); + UpdateAutoLootRareIndicator(); + UpdateWebSocketStatus(); + } + catch (Exception ex) + { + PluginCore.WriteToChat($"Error initializing main tab controls: {ex.Message}"); + } + } + + private void InitializeSettingsTabControls() + { + try + { + // Settings tab controls + chkRareMetaEnabled = GetControl("chkRareMetaEnabled"); + chkRemoteCommandsEnabled = GetControl("chkRemoteCommandsEnabled"); + chkHttpServerEnabled = GetControl("chkHttpServerEnabled"); + chkWebSocketEnabled = GetControl("chkWebSocketEnabled"); + chkTelemetryEnabled = GetControl("chkTelemetryEnabled"); + txtCharTag = GetControl("txtCharTag"); + txtVTankPath = GetControl("txtVTankPath"); + + // Hook up settings events + if (chkRareMetaEnabled != null) + chkRareMetaEnabled.Change += OnRareMetaSettingChanged; + if (chkRemoteCommandsEnabled != null) + chkRemoteCommandsEnabled.Change += OnRemoteCommandsSettingChanged; + if (chkHttpServerEnabled != null) + chkHttpServerEnabled.Change += OnHttpServerSettingChanged; + if (chkWebSocketEnabled != null) + chkWebSocketEnabled.Change += OnWebSocketSettingChanged; + if (chkTelemetryEnabled != null) + chkTelemetryEnabled.Change += OnTelemetrySettingChanged; + if (txtCharTag != null) + txtCharTag.Change += OnCharTagChanged; + if (txtVTankPath != null) + txtVTankPath.Change += OnVTankPathChanged; + + // Load current settings + LoadCurrentSettings(); + } + catch (Exception ex) + { + PluginCore.WriteToChat($"Error initializing settings tab controls: {ex.Message}"); + } + } + + private void InitializeStatisticsTabControls() + { + try + { + // Statistics tab controls + lblDetailedKillsValue = GetControl("lblDetailedKillsValue"); + lblBestHourValue = GetControl("lblBestHourValue"); + lblAverageKillsValue = GetControl("lblAverageKillsValue"); + lblRareStatsValue = GetControl("lblRareStatsValue"); + lblRareRateValue = GetControl("lblRareRateValue"); + lblSessionTimeValue = GetControl("lblSessionTimeValue"); + lblLastKillValue = GetControl("lblLastKillValue"); + btnResetStats = GetControl("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 + { + // Basic navigation tab controls + chkNavVisualizationEnabled = GetControl("chkNavVisualizationEnabled"); + cmbNavFiles = GetControl("cmbNavFiles"); + btnRefreshNavFiles = GetControl("btnRefreshNavFiles"); + lblNavStatus = GetControl("lblNavStatus"); + btnLoadRoute = GetControl("btnLoadRoute"); + btnClearRoute = GetControl("btnClearRoute"); + + // Hook up basic 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}"); + } + } + #endregion + + #region Event Handlers - Settings Tab + private void OnRareMetaSettingChanged(object sender, EventArgs e) + { + try + { + PluginSettings.Instance.RareMetaEnabled = chkRareMetaEnabled.Checked; + PluginCore.RareMetaEnabled = chkRareMetaEnabled.Checked; + UpdateAutoLootRareIndicator(); + PluginCore.WriteToChat($"Rare meta automation {(chkRareMetaEnabled.Checked ? "ENABLED" : "DISABLED")}."); + } + catch (Exception ex) + { + PluginCore.WriteToChat($"Error in rare meta setting change: {ex.Message}"); + } + } + + private void OnRemoteCommandsSettingChanged(object sender, EventArgs e) + { + try + { + PluginSettings.Instance.RemoteCommandsEnabled = chkRemoteCommandsEnabled.Checked; + } + catch (Exception ex) + { + PluginCore.WriteToChat($"Error in remote commands setting change: {ex.Message}"); + } + } + + private void OnHttpServerSettingChanged(object sender, EventArgs e) + { + try + { + PluginSettings.Instance.HttpServerEnabled = chkHttpServerEnabled.Checked; + if (chkHttpServerEnabled.Checked) + HttpCommandServer.Start(); + else + HttpCommandServer.Stop(); + } + catch (Exception ex) + { + PluginCore.WriteToChat($"Error in HTTP server setting change: {ex.Message}"); + } + } + + private void OnWebSocketSettingChanged(object sender, EventArgs e) + { + try + { + PluginSettings.Instance.WebSocketEnabled = chkWebSocketEnabled.Checked; + if (chkWebSocketEnabled.Checked) + { + WebSocket.Start(); + PluginCore.WriteToChat("WebSocket streaming ENABLED."); + } + else + { + WebSocket.Stop(); + PluginCore.WriteToChat("WebSocket streaming DISABLED."); + } + UpdateWebSocketStatus(); + } + catch (Exception ex) + { + PluginCore.WriteToChat($"Error in WebSocket setting change: {ex.Message}"); + } + } + + private void OnTelemetrySettingChanged(object sender, EventArgs e) + { + try + { + PluginSettings.Instance.TelemetryEnabled = chkTelemetryEnabled.Checked; + if (chkTelemetryEnabled.Checked) + Telemetry.Start(); + else + Telemetry.Stop(); + } + catch (Exception ex) + { + PluginCore.WriteToChat($"Error in telemetry setting change: {ex.Message}"); + } + } + + private void OnCharTagChanged(object sender, EventArgs e) + { + try + { + PluginSettings.Instance.CharTag = txtCharTag.Text; + } + catch (Exception ex) + { + PluginCore.WriteToChat($"Error in char tag change: {ex.Message}"); + } + } + + private void OnVTankPathChanged(object sender, EventArgs e) + { + try + { + PluginSettings.Instance.VTankProfilesPath = txtVTankPath.Text; + // Refresh navigation system with new path + if (PluginCore.navVisualization != null) + { + PluginCore.navVisualization.RefreshNavFileList(); + RefreshNavFileList(); + UpdateNavigationStatus(); + } + } + catch (Exception ex) + { + PluginCore.WriteToChat($"Error in VTank path change: {ex.Message}"); + } + } + + private void LoadCurrentSettings() + { + try + { + if (PluginSettings.Instance != null) + { + if (chkRareMetaEnabled != null) + chkRareMetaEnabled.Checked = PluginSettings.Instance.RareMetaEnabled; + if (chkRemoteCommandsEnabled != null) + chkRemoteCommandsEnabled.Checked = PluginSettings.Instance.RemoteCommandsEnabled; + if (chkHttpServerEnabled != null) + chkHttpServerEnabled.Checked = PluginSettings.Instance.HttpServerEnabled; + if (chkWebSocketEnabled != null) + chkWebSocketEnabled.Checked = PluginSettings.Instance.WebSocketEnabled; + if (chkTelemetryEnabled != null) + chkTelemetryEnabled.Checked = PluginSettings.Instance.TelemetryEnabled; + if (txtCharTag != null) + txtCharTag.Text = PluginSettings.Instance.CharTag ?? "default"; + if (txtVTankPath != null) + 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) + { + try + { + PluginCore.RestartStats(); + sessionStartTime = DateTime.Now; + bestHourlyKills = 0; + UpdateStatistics(); + } + catch (Exception ex) + { + PluginCore.WriteToChat($"Error resetting stats: {ex.Message}"); + } + } + #endregion + + #region Event Handlers - Navigation Tab + private void OnNavVisualizationEnabledChanged(object sender, EventArgs e) + { + try + { + if (PluginCore.navVisualization != null) + { + PluginCore.navVisualization.SetEnabled(chkNavVisualizationEnabled.Checked); + UpdateNavigationStatus(); + } + } + catch (Exception ex) + { + PluginCore.WriteToChat($"Error in nav visualization change: {ex.Message}"); + } + } + + private void OnRefreshNavFilesClick(object sender, EventArgs e) + { + try + { + RefreshNavFileList(); + } + catch (Exception ex) + { + PluginCore.WriteToChat($"Error refreshing nav files: {ex.Message}"); + } + } + + private void OnLoadRouteClick(object sender, EventArgs e) + { + try + { + // Load from dropdown selection + string routeName = null; + + if (cmbNavFiles != null && cmbNavFiles.Current >= 0 && cmbNavFiles.Count > 0 && + cmbNavFiles.Current < cmbNavFiles.Count) + { + routeName = ((HudStaticText)cmbNavFiles[cmbNavFiles.Current]).Text; + } + + if (!string.IsNullOrEmpty(routeName) && routeName != "None") + { + PluginCore.navVisualization.LoadRoute(routeName); + UpdateNavigationStatus(); + } + else + { + PluginCore.WriteToChat("[NavViz] Please select a route from the dropdown"); + } + } + catch (Exception ex) + { + PluginCore.WriteToChat($"[NavViz] Error loading route: {ex.Message}"); + } + } + + private void OnClearRouteClick(object sender, EventArgs e) + { + try + { + if (PluginCore.navVisualization != null) + { + PluginCore.navVisualization.LoadRoute("None"); + // Clear dropdown selection + if (cmbNavFiles != null && cmbNavFiles.Count > 0) + { + cmbNavFiles.Current = 0; // Select "None" which should be at index 0 + } + UpdateNavigationStatus(); + } + } + catch (Exception ex) + { + PluginCore.WriteToChat($"Error clearing route: {ex.Message}"); + } + } + + 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) + { + PluginCore.navVisualization.RefreshNavFileList(); + + // Update the basic dropdown + PopulateNavFileDropdown(); + + } + } + 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 Public Update Methods (maintain compatibility with existing code) + public static void UpdateKillStats(int totalKills, double killsPer5Min, double killsPerHour) + { + try + { + if (instance == null) return; + + 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 (killsPerHour > instance.bestHourlyKills) + { + instance.bestHourlyKills = killsPerHour; + if (instance.lblBestHourValue != null) + instance.lblBestHourValue.Text = $"{instance.bestHourlyKills:F2} kills/hr"; + } + + // Update status displays + 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) + { + try + { + if (instance?.chkRareMetaEnabled != null) + instance.chkRareMetaEnabled.Checked = enabled; + instance?.UpdateAutoLootRareIndicator(); + } + catch (Exception ex) + { + PluginCore.WriteToChat($"Error setting rare meta toggle state: {ex.Message}"); + } + } + + public static void RefreshSettingsFromConfig() + { + try + { + instance?.LoadCurrentSettings(); + instance?.UpdateAutoLootRareIndicator(); + instance?.UpdateWebSocketStatus(); + } + catch (Exception ex) + { + PluginCore.WriteToChat($"Error refreshing settings from config: {ex.Message}"); + } + } + #endregion + + #region Status Update Methods + 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]"; + // Try to set green color for ON status + try { lblAutoLootRare.TextColor = System.Drawing.Color.FromArgb(0, 128, 0); } catch { } + } + else + { + lblAutoLootRare.Text = "Auto Loot Rare: [OFF]"; + // Try to set red color for OFF status + try { lblAutoLootRare.TextColor = System.Drawing.Color.FromArgb(255, 0, 0); } catch { } + } + } + } + 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]"; + // Try to set green color for CONNECTED status + try { lblWebSocketStatus.TextColor = System.Drawing.Color.FromArgb(0, 128, 0); } catch { } + } + else + { + lblWebSocketStatus.Text = "WebSocket: [DISCONNECTED]"; + // Try to set red color for DISCONNECTED status + try { lblWebSocketStatus.TextColor = System.Drawing.Color.FromArgb(255, 0, 0); } catch { } + } + } + } + catch + { + if (lblWebSocketStatus != null) + lblWebSocketStatus.Text = "WebSocket: Unknown"; + } + } + + 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}"); + } + } + #endregion + + #region Helper Methods + private void PopulateNavFileDropdown() + { + try + { + if (cmbNavFiles != null && PluginCore.navVisualization != null) + { + cmbNavFiles.Clear(); + cmbNavFiles.AddItem("None", "None"); + + foreach (string navFile in PluginCore.navVisualization.AvailableNavFiles) + { + cmbNavFiles.AddItem(navFile, navFile); + } + + if (cmbNavFiles.Count > 0) + cmbNavFiles.Current = 0; // Select "None" which should be at index 0 + + } + } + catch (Exception ex) + { + PluginCore.WriteToChat($"Error populating nav file dropdown: {ex.Message}"); + } + } + #endregion + + #region IDisposable Override + protected override void Dispose(bool disposing) + { + if (disposing) + { + try + { + // Unsubscribe from events to prevent memory leaks + + // Settings tab event cleanup + if (chkRareMetaEnabled != null) + chkRareMetaEnabled.Change -= OnRareMetaSettingChanged; + if (chkRemoteCommandsEnabled != null) + chkRemoteCommandsEnabled.Change -= OnRemoteCommandsSettingChanged; + if (chkHttpServerEnabled != null) + chkHttpServerEnabled.Change -= OnHttpServerSettingChanged; + if (chkWebSocketEnabled != null) + chkWebSocketEnabled.Change -= OnWebSocketSettingChanged; + if (chkTelemetryEnabled != null) + chkTelemetryEnabled.Change -= OnTelemetrySettingChanged; + if (txtCharTag != null) + txtCharTag.Change -= OnCharTagChanged; + if (txtVTankPath != null) + txtVTankPath.Change -= OnVTankPathChanged; + + // Statistics tab event cleanup + if (btnResetStats != null) + btnResetStats.Hit -= OnResetStatsClick; + + // Navigation tab event cleanup + if (chkNavVisualizationEnabled != null) + chkNavVisualizationEnabled.Change -= OnNavVisualizationEnabledChanged; + if (btnRefreshNavFiles != null) + btnRefreshNavFiles.Hit -= OnRefreshNavFilesClick; + if (btnLoadRoute != null) + btnLoadRoute.Hit -= OnLoadRouteClick; + if (btnClearRoute != null) + btnClearRoute.Hit -= OnClearRouteClick; + + // No enhanced events to clean up + } + catch (Exception ex) + { + PluginCore.WriteToChat($"Error cleaning up VVS view events: {ex.Message}"); + } + } + + // Call base dispose + base.Dispose(disposing); + } + #endregion + } +} \ No newline at end of file diff --git a/MosswartMassacre/Wrapper.cs b/MosswartMassacre/Wrapper.cs deleted file mode 100644 index 7cca722..0000000 --- a/MosswartMassacre/Wrapper.cs +++ /dev/null @@ -1,427 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -//File: Wrapper.cs -// -//Description: Contains the interface definitions for the MetaViewWrappers classes. -// -//References required: -// System.Drawing -// -//This file is Copyright (c) 2010 VirindiPlugins -// -//Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -//The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -/////////////////////////////////////////////////////////////////////////////// - -using System; -using System.Collections.Generic; -using System.Text; - -#if METAVIEW_PUBLIC_NS -namespace MetaViewWrappers -#else -namespace MyClasses.MetaViewWrappers -#endif -{ -#if VVS_WRAPPERS_PUBLIC - public -#else - internal -#endif - delegate void dClickedList(object sender, int row, int col); - - - #region EventArgs Classes - -#if VVS_WRAPPERS_PUBLIC - public -#else - internal -#endif - class MVControlEventArgs : EventArgs - { - private int id; - - internal MVControlEventArgs(int ID) - { - this.id = ID; - } - - public int Id - { - get { return this.id; } - } - } - -#if VVS_WRAPPERS_PUBLIC - public -#else - internal -#endif - class MVIndexChangeEventArgs : MVControlEventArgs - { - private int index; - - internal MVIndexChangeEventArgs(int ID, int Index) - : base(ID) - { - this.index = Index; - } - - public int Index - { - get { return this.index; } - } - } - -#if VVS_WRAPPERS_PUBLIC - public -#else - internal -#endif - class MVListSelectEventArgs : MVControlEventArgs - { - private int row; - private int col; - - internal MVListSelectEventArgs(int ID, int Row, int Column) - : base(ID) - { - this.row = Row; - this.col = Column; - } - - public int Row - { - get { return this.row; } - } - - public int Column - { - get { return this.col; } - } - } - -#if VVS_WRAPPERS_PUBLIC - public -#else - internal -#endif - class MVCheckBoxChangeEventArgs : MVControlEventArgs - { - private bool check; - - internal MVCheckBoxChangeEventArgs(int ID, bool Check) - : base(ID) - { - this.check = Check; - } - - public bool Checked - { - get { return this.check; } - } - } - -#if VVS_WRAPPERS_PUBLIC - public -#else - internal -#endif - class MVTextBoxChangeEventArgs : MVControlEventArgs - { - private string text; - - internal MVTextBoxChangeEventArgs(int ID, string text) - : base(ID) - { - this.text = text; - } - - public string Text - { - get { return this.text; } - } - } - -#if VVS_WRAPPERS_PUBLIC - public -#else - internal -#endif - class MVTextBoxEndEventArgs : MVControlEventArgs - { - private bool success; - - internal MVTextBoxEndEventArgs(int ID, bool success) - : base(ID) - { - this.success = success; - } - - public bool Success - { - get { return this.success; } - } - } - - #endregion EventArgs Classes - - - #region View - -#if VVS_WRAPPERS_PUBLIC - public -#else - internal -#endif - interface IView: IDisposable - { - void Initialize(Decal.Adapter.Wrappers.PluginHost p, string pXML); - void InitializeRawXML(Decal.Adapter.Wrappers.PluginHost p, string pXML); - void Initialize(Decal.Adapter.Wrappers.PluginHost p, string pXML, string pWindowKey); - void InitializeRawXML(Decal.Adapter.Wrappers.PluginHost p, string pXML, string pWindowKey); - - void SetIcon(int icon, int iconlibrary); - void SetIcon(int portalicon); - - string Title { get; set; } - bool Visible { get; set; } -#if !VVS_WRAPPERS_PUBLIC - ViewSystemSelector.eViewSystem ViewType { get; } -#endif - - System.Drawing.Point Location { get; set; } - System.Drawing.Rectangle Position { get; set; } - System.Drawing.Size Size { get; } - - IControl this[string id] { get; } - - void Activate(); - void Deactivate(); - bool Activated { get; set; } - } - - #endregion View - - #region Controls - -#if VVS_WRAPPERS_PUBLIC - public -#else - internal -#endif - interface IControl : IDisposable - { - string Name { get; } - bool Visible { get; set; } - string TooltipText { get; set;} - int Id { get; } - System.Drawing.Rectangle LayoutPosition { get; set; } - } - -#if VVS_WRAPPERS_PUBLIC - public -#else - internal -#endif - interface IButton : IControl - { - string Text { get; set; } - event EventHandler Hit; - event EventHandler Click; - System.Drawing.Color TextColor { get; set; } - } - -#if VVS_WRAPPERS_PUBLIC - public -#else - internal -#endif - interface ICheckBox : IControl - { - string Text { get; set; } - bool Checked { get; set; } - event EventHandler Change; - event EventHandler Change_Old; - } - -#if VVS_WRAPPERS_PUBLIC - public -#else - internal -#endif - interface ITextBox : IControl - { - string Text { get; set; } - event EventHandler Change; - event EventHandler Change_Old; - event EventHandler End; - int Caret { get; set; } - } - -#if VVS_WRAPPERS_PUBLIC - public -#else - internal -#endif - interface ICombo : IControl - { - IComboIndexer Text { get; } - IComboDataIndexer Data { get; } - int Count { get; } - int Selected { get; set; } - event EventHandler Change; - event EventHandler Change_Old; - void Add(string text); - void Add(string text, object obj); - void Insert(int index, string text); - void RemoveAt(int index); - void Remove(int index); - void Clear(); - } - -#if VVS_WRAPPERS_PUBLIC - public -#else - internal -#endif - interface IComboIndexer - { - string this[int index] { get; set; } - } - -#if VVS_WRAPPERS_PUBLIC - public -#else - internal -#endif - interface IComboDataIndexer - { - object this[int index] { get; set; } - } - -#if VVS_WRAPPERS_PUBLIC - public -#else - internal -#endif - interface ISlider : IControl - { - int Position { get; set; } - event EventHandler Change; - event EventHandler Change_Old; - int Maximum { get; set; } - int Minimum { get; set; } - } - -#if VVS_WRAPPERS_PUBLIC - public -#else - internal -#endif - interface IList : IControl - { - event EventHandler Selected; - event dClickedList Click; - void Clear(); - IListRow this[int row] { get; } - IListRow AddRow(); - IListRow Add(); - IListRow InsertRow(int pos); - IListRow Insert(int pos); - int RowCount { get; } - void RemoveRow(int index); - void Delete(int index); - int ColCount { get; } - int ScrollPosition { get; set;} - } - -#if VVS_WRAPPERS_PUBLIC - public -#else - internal -#endif - interface IListRow - { - IListCell this[int col] { get; } - } - -#if VVS_WRAPPERS_PUBLIC - public -#else - internal -#endif - interface IListCell - { - System.Drawing.Color Color { get; set; } - int Width { get; set; } - object this[int subval] { get; set; } - void ResetColor(); - } - -#if VVS_WRAPPERS_PUBLIC - public -#else - internal -#endif - interface IStaticText : IControl - { - string Text { get; set; } - event EventHandler Click; - } - -#if VVS_WRAPPERS_PUBLIC - public -#else - internal -#endif - interface INotebook : IControl - { - event EventHandler Change; - int ActiveTab { get; set; } - } - -#if VVS_WRAPPERS_PUBLIC - public -#else - internal -#endif - interface IProgressBar : IControl - { - int Position { get; set; } - int Value { get; set; } - string PreText { get; set; } - int MaxValue { get; set; } - } - -#if VVS_WRAPPERS_PUBLIC - public -#else - internal -#endif - interface IImageButton : IControl - { - event EventHandler Click; - void SetImages(int unpressed, int pressed); - void SetImages(int hmodule, int unpressed, int pressed); - int Background { set; } - System.Drawing.Color Matte { set; } - } - - #endregion Controls -} diff --git a/MosswartMassacre/Wrapper_Decal.cs b/MosswartMassacre/Wrapper_Decal.cs deleted file mode 100644 index a917ca8..0000000 --- a/MosswartMassacre/Wrapper_Decal.cs +++ /dev/null @@ -1,1120 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -//File: Wrapper_Decal.cs -// -//Description: Contains MetaViewWrapper classes implementing Decal views. -// -//References required: -// System.Drawing -// Decal.Adapter -// -//This file is Copyright (c) 2010 VirindiPlugins -// -//Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -//The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -/////////////////////////////////////////////////////////////////////////////// - -using System; -using System.Collections.Generic; -using System.Text; - -#if METAVIEW_PUBLIC_NS -namespace MetaViewWrappers.DecalControls -#else -namespace MyClasses.MetaViewWrappers.DecalControls -#endif - -{ -#if VVS_WRAPPERS_PUBLIC - public -#else - internal -#endif - class View : IView - { - Decal.Adapter.Wrappers.ViewWrapper myView; - public Decal.Adapter.Wrappers.ViewWrapper Underlying { get { return myView; } } - - #region IView Members - - public void Initialize(Decal.Adapter.Wrappers.PluginHost p, string pXML) - { - myView = p.LoadViewResource(pXML); - } - - public void InitializeRawXML(Decal.Adapter.Wrappers.PluginHost p, string pXML) - { - myView = p.LoadView(pXML); - } - - public void Initialize(Decal.Adapter.Wrappers.PluginHost p, string pXML, string pWindowKey) - { - myView = p.LoadViewResource(pXML); - } - - public void InitializeRawXML(Decal.Adapter.Wrappers.PluginHost p, string pXML, string pWindowKey) - { - myView = p.LoadView(pXML); - } - - public void SetIcon(int icon, int iconlibrary) - { - myView.SetIcon(icon, iconlibrary); - } - - public void SetIcon(int portalicon) - { - //throw new Exception("The method or operation is not implemented."); - } - - public string Title - { - get - { - return myView.Title; - } - set - { - myView.Title = value; - } - } - - public bool Visible - { - get - { - return myView.Activated; - } - set - { - myView.Activated = value; - } - } - - public bool Activated - { - get - { - return Visible; - } - set - { - Visible = value; - } - } - - public void Activate() - { - Visible = true; - } - - public void Deactivate() - { - Visible = false; - } - - public System.Drawing.Point Location - { - get - { - return new System.Drawing.Point(myView.Position.X, myView.Position.Y); - } - set - { - int w = myView.Position.Width; - int h = myView.Position.Height; - myView.Position = new System.Drawing.Rectangle(value.X, value.Y, w, h); - } - } - - public System.Drawing.Rectangle Position - { - get - { - return myView.Position; - } - set - { - myView.Position = value; - } - } - - public System.Drawing.Size Size - { - get - { - return new System.Drawing.Size(myView.Position.Width, myView.Position.Height); - } - } - -#if VVS_WRAPPERS_PUBLIC - internal -#else - public -#endif - ViewSystemSelector.eViewSystem ViewType { get { return ViewSystemSelector.eViewSystem.DecalInject; } } - Dictionary CreatedControlsByName = new Dictionary(); - - public IControl this[string id] - { - get - { - if (CreatedControlsByName.ContainsKey(id)) return CreatedControlsByName[id]; - - Control ret = null; - Decal.Adapter.Wrappers.IControlWrapper iret = myView.Controls[id]; - if (iret.GetType() == typeof(Decal.Adapter.Wrappers.PushButtonWrapper)) - ret = new Button(); - if (iret.GetType() == typeof(Decal.Adapter.Wrappers.CheckBoxWrapper)) - ret = new CheckBox(); - if (iret.GetType() == typeof(Decal.Adapter.Wrappers.TextBoxWrapper)) - ret = new TextBox(); - if (iret.GetType() == typeof(Decal.Adapter.Wrappers.ChoiceWrapper)) - ret = new Combo(); - if (iret.GetType() == typeof(Decal.Adapter.Wrappers.SliderWrapper)) - ret = new Slider(); - if (iret.GetType() == typeof(Decal.Adapter.Wrappers.ListWrapper)) - ret = new List(); - if (iret.GetType() == typeof(Decal.Adapter.Wrappers.StaticWrapper)) - ret = new StaticText(); - if (iret.GetType() == typeof(Decal.Adapter.Wrappers.NotebookWrapper)) - ret = new Notebook(); - if (iret.GetType() == typeof(Decal.Adapter.Wrappers.ProgressWrapper)) - ret = new ProgressBar(); - if (iret.GetType() == typeof(Decal.Adapter.Wrappers.ButtonWrapper)) - ret = new ImageButton(); - - if (ret == null) return null; - - ret.myControl = iret; - ret.myName = id; - ret.Initialize(); - allocatedcontrols.Add(ret); - CreatedControlsByName[id] = ret; - return ret; - } - } - - List allocatedcontrols = new List(); - - #endregion - - #region IDisposable Members - - bool disposed = false; - public void Dispose() - { - if (disposed) return; - disposed = true; - GC.SuppressFinalize(this); - - foreach (Control c in allocatedcontrols) - c.Dispose(); - - myView.Dispose(); - } - - #endregion - } - -#if VVS_WRAPPERS_PUBLIC - public -#else - internal -#endif - class Control : IControl - { - internal Decal.Adapter.Wrappers.IControlWrapper myControl; - public Decal.Adapter.Wrappers.IControlWrapper Underlying { get { return myControl; } } - internal string myName; - - public virtual void Initialize() - { - - } - - #region IControl Members - - public string Name - { - get { return myName; } - } - - public bool Visible - { - get { return true; } - set { } - } - - public string TooltipText - { - get - { - return ""; - } - set - { - - } - } - - public int Id - { - get - { - return myControl.Id; - } - } - - public System.Drawing.Rectangle LayoutPosition - { - get - { -#if DECAL_INTEROP - //This is kinda bad, but whatever - Decal.Interop.Inject.ILayer Ly = (Decal.Interop.Inject.ILayer)(Underlying.Underlying); - Decal.Interop.Core.tagRECT rct = Ly.get_Position(); - return new System.Drawing.Rectangle(rct.left, rct.top, rct.right - rct.left, rct.bottom - rct.top); -#else -#warning DECAL_INTEROP not defined, MetaViewWrappers.DecalControls.Control.LayoutPosition will not be available. - return new System.Drawing.Rectangle(); -#endif - } - set - { -#if DECAL_INTEROP - Decal.Interop.Inject.ILayer Ly = (Decal.Interop.Inject.ILayer)(Underlying.Underlying); - Decal.Interop.Core.tagRECT rct = new Decal.Interop.Core.tagRECT(); - rct.left = value.Left; - rct.top = value.Top; - rct.right = value.Right; - rct.bottom = value.Bottom; - Ly.set_Position(ref rct); -#endif - } - } - - #endregion - - #region IDisposable Members - - bool disposed = false; - public virtual void Dispose() - { - if (disposed) return; - disposed = true; - - //myControl.Dispose(); - } - - #endregion - } - -#if VVS_WRAPPERS_PUBLIC - public -#else - internal -#endif - class Button : Control, IButton - { - public override void Initialize() - { - base.Initialize(); - ((Decal.Adapter.Wrappers.PushButtonWrapper)myControl).Hit += new EventHandler(Button_Hit); - ((Decal.Adapter.Wrappers.PushButtonWrapper)myControl).Click += new EventHandler(Button_Click); - } - - public override void Dispose() - { - base.Dispose(); - ((Decal.Adapter.Wrappers.PushButtonWrapper)myControl).Hit -= new EventHandler(Button_Hit); - ((Decal.Adapter.Wrappers.PushButtonWrapper)myControl).Click -= new EventHandler(Button_Click); - } - - void Button_Hit(object sender, Decal.Adapter.ControlEventArgs e) - { - if (Hit != null) - Hit(this, null); - } - - void Button_Click(object sender, Decal.Adapter.ControlEventArgs e) - { - if (Click != null) - Click(this, new MVControlEventArgs(this.Id)); - } - - #region IButton Members - - public string Text - { - get - { - return ((Decal.Adapter.Wrappers.PushButtonWrapper)myControl).Text; - //throw new Exception("The method or operation is not implemented."); - } - set - { - ((Decal.Adapter.Wrappers.PushButtonWrapper)myControl).Text = value; - //throw new Exception("The method or operation is not implemented."); - } - } - - public System.Drawing.Color TextColor - { - get - { - return ((Decal.Adapter.Wrappers.PushButtonWrapper)myControl).TextColor; - } - set - { - ((Decal.Adapter.Wrappers.PushButtonWrapper)myControl).TextColor = value; - } - } - - public event EventHandler Hit; - public event EventHandler Click; - - #endregion - } - -#if VVS_WRAPPERS_PUBLIC - public -#else - internal -#endif - class CheckBox : Control, ICheckBox - { - public override void Initialize() - { - base.Initialize(); - ((Decal.Adapter.Wrappers.CheckBoxWrapper)myControl).Change += new EventHandler(CheckBox_Change); - } - - public override void Dispose() - { - base.Dispose(); - ((Decal.Adapter.Wrappers.CheckBoxWrapper)myControl).Change -= new EventHandler(CheckBox_Change); - } - - void CheckBox_Change(object sender, Decal.Adapter.CheckBoxChangeEventArgs e) - { - if (Change != null) - Change(this, new MVCheckBoxChangeEventArgs(this.Id, Checked)); - if (Change_Old != null) - Change_Old(this, null); - } - - #region ICheckBox Members - - public string Text - { - get - { - return ((Decal.Adapter.Wrappers.CheckBoxWrapper)myControl).Text; - } - set - { - ((Decal.Adapter.Wrappers.CheckBoxWrapper)myControl).Text = value; - } - } - - public bool Checked - { - get - { - return ((Decal.Adapter.Wrappers.CheckBoxWrapper)myControl).Checked; - } - set - { - ((Decal.Adapter.Wrappers.CheckBoxWrapper)myControl).Checked = value; - } - } - - public event EventHandler Change; - public event EventHandler Change_Old; - - #endregion - } - -#if VVS_WRAPPERS_PUBLIC - public -#else - internal -#endif - class TextBox : Control, ITextBox - { - public override void Initialize() - { - base.Initialize(); - ((Decal.Adapter.Wrappers.TextBoxWrapper)myControl).Change += new EventHandler(TextBox_Change); - ((Decal.Adapter.Wrappers.TextBoxWrapper)myControl).End += new EventHandler(TextBox_End); - } - - public override void Dispose() - { - base.Dispose(); - ((Decal.Adapter.Wrappers.TextBoxWrapper)myControl).Change -= new EventHandler(TextBox_Change); - ((Decal.Adapter.Wrappers.TextBoxWrapper)myControl).End -= new EventHandler(TextBox_End); - } - - void TextBox_Change(object sender, Decal.Adapter.TextBoxChangeEventArgs e) - { - if (Change != null) - Change(this, new MVTextBoxChangeEventArgs(this.Id, e.Text)); - if (Change_Old != null) - Change_Old(this, null); - } - - void TextBox_End(object sender, Decal.Adapter.TextBoxEndEventArgs e) - { - if (End != null) - End(this, new MVTextBoxEndEventArgs(this.Id, e.Success)); - } - - #region ITextBox Members - - public string Text - { - get - { - return ((Decal.Adapter.Wrappers.TextBoxWrapper)myControl).Text; - } - set - { - ((Decal.Adapter.Wrappers.TextBoxWrapper)myControl).Text = value; - } - } - - public int Caret - { - get - { - return ((Decal.Adapter.Wrappers.TextBoxWrapper)myControl).Caret; - } - set - { - ((Decal.Adapter.Wrappers.TextBoxWrapper)myControl).Caret = value; - } - } - - public event EventHandler Change; - public event EventHandler Change_Old; - public event EventHandler End; - - #endregion - } - -#if VVS_WRAPPERS_PUBLIC - public -#else - internal -#endif - class Combo : Control, ICombo - { - public override void Initialize() - { - base.Initialize(); - ((Decal.Adapter.Wrappers.ChoiceWrapper)myControl).Change += new EventHandler(Combo_Change); - } - - public override void Dispose() - { - base.Dispose(); - ((Decal.Adapter.Wrappers.ChoiceWrapper)myControl).Change -= new EventHandler(Combo_Change); - } - - void Combo_Change(object sender, Decal.Adapter.IndexChangeEventArgs e) - { - if (Change != null) - Change(this, new MVIndexChangeEventArgs(this.Id, e.Index)); - if (Change_Old != null) - Change_Old(this, null); - } - - #region ICombo Members - - public IComboIndexer Text - { - get - { - return new ComboIndexer(this); - } - } - - public IComboDataIndexer Data - { - get - { - return new ComboDataIndexer(this); - } - } - - public int Count - { - get - { - return ((Decal.Adapter.Wrappers.ChoiceWrapper)myControl).Count; - } - } - - public int Selected - { - get - { - return ((Decal.Adapter.Wrappers.ChoiceWrapper)myControl).Selected; - } - set - { - ((Decal.Adapter.Wrappers.ChoiceWrapper)myControl).Selected = value; - } - } - - public event EventHandler Change; - public event EventHandler Change_Old; - - public void Add(string text) - { - ((Decal.Adapter.Wrappers.ChoiceWrapper)myControl).Add(text, null); - } - - public void Add(string text, object obj) - { - ((Decal.Adapter.Wrappers.ChoiceWrapper)myControl).Add(text, obj); - } - - public void Insert(int index, string text) - { - throw new Exception("The method or operation is not implemented."); - } - - public void RemoveAt(int index) - { - ((Decal.Adapter.Wrappers.ChoiceWrapper)myControl).Remove(index); - } - - public void Remove(int index) - { - RemoveAt(index); - } - - public void Clear() - { - ((Decal.Adapter.Wrappers.ChoiceWrapper)myControl).Clear(); - } - - #endregion - - internal class ComboIndexer: IComboIndexer - { - Combo myCombo; - internal ComboIndexer(Combo c) - { - myCombo = c; - } - - #region IComboIndexer Members - - public string this[int index] - { - get - { - return ((Decal.Adapter.Wrappers.ChoiceWrapper)myCombo.myControl).Text[index]; - } - set - { - ((Decal.Adapter.Wrappers.ChoiceWrapper)myCombo.myControl).Text[index] = value; - } - } - - #endregion - } - - internal class ComboDataIndexer : IComboDataIndexer - { - Combo myCombo; - internal ComboDataIndexer(Combo c) - { - myCombo = c; - } - - #region IComboIndexer Members - - public object this[int index] - { - get - { - return ((Decal.Adapter.Wrappers.ChoiceWrapper)myCombo.myControl).Data[index]; - } - set - { - ((Decal.Adapter.Wrappers.ChoiceWrapper)myCombo.myControl).Data[index] = value; - } - } - - #endregion - } - } - -#if VVS_WRAPPERS_PUBLIC - public -#else - internal -#endif - class Slider : Control, ISlider - { - public override void Initialize() - { - base.Initialize(); - ((Decal.Adapter.Wrappers.SliderWrapper)myControl).Change += new EventHandler(Slider_Change); - } - - public override void Dispose() - { - base.Dispose(); - ((Decal.Adapter.Wrappers.SliderWrapper)myControl).Change -= new EventHandler(Slider_Change); - } - - void Slider_Change(object sender, Decal.Adapter.IndexChangeEventArgs e) - { - if (Change != null) - Change(this, new MVIndexChangeEventArgs(this.Id, e.Index)); - if (Change_Old != null) - Change_Old(this, null); - } - - #region ISlider Members - - public int Position - { - get - { - return ((Decal.Adapter.Wrappers.SliderWrapper)myControl).SliderPostition; - } - set - { - ((Decal.Adapter.Wrappers.SliderWrapper)myControl).SliderPostition = value; - } - } - - public event EventHandler Change; - public event EventHandler Change_Old; - - public int Maximum - { - get - { - return ((Decal.Adapter.Wrappers.SliderWrapper)myControl).Maximum; - } - set - { - ((Decal.Adapter.Wrappers.SliderWrapper)myControl).Maximum = value; - } - } - public int Minimum - { - get - { - return ((Decal.Adapter.Wrappers.SliderWrapper)myControl).Minimum; - } - set - { - ((Decal.Adapter.Wrappers.SliderWrapper)myControl).Minimum = value; - } - } - - #endregion - } - -#if VVS_WRAPPERS_PUBLIC - public -#else - internal -#endif - class List : Control, IList - { - public override void Initialize() - { - base.Initialize(); - ((Decal.Adapter.Wrappers.ListWrapper)myControl).Selected += new EventHandler(List_Selected); - } - - public override void Dispose() - { - base.Dispose(); - ((Decal.Adapter.Wrappers.ListWrapper)myControl).Selected -= new EventHandler(List_Selected); - } - - void List_Selected(object sender, Decal.Adapter.ListSelectEventArgs e) - { - if (Click != null) - Click(this, e.Row, e.Column); - if (Selected != null) - Selected(this, new MVListSelectEventArgs(this.Id, e.Row, e.Column)); - } - - #region IList Members - - public event dClickedList Click; - public event EventHandler Selected; - - public void Clear() - { - ((Decal.Adapter.Wrappers.ListWrapper)myControl).Clear(); - } - - public IListRow this[int row] - { - get - { - return new ListRow(this, row); - } - } - - public IListRow AddRow() - { - ((Decal.Adapter.Wrappers.ListWrapper)myControl).Add(); - return new ListRow(this, ((Decal.Adapter.Wrappers.ListWrapper)myControl).RowCount - 1); - } - - public IListRow Add() - { - return AddRow(); - } - - public IListRow InsertRow(int pos) - { - ((Decal.Adapter.Wrappers.ListWrapper)myControl).Insert(pos); - return new ListRow(this, pos); - } - - public IListRow Insert(int pos) - { - return InsertRow(pos); - } - - public int RowCount - { - get { return ((Decal.Adapter.Wrappers.ListWrapper)myControl).RowCount; } - } - - public void RemoveRow(int index) - { - ((Decal.Adapter.Wrappers.ListWrapper)myControl).Delete(index); - } - - public void Delete(int index) - { - RemoveRow(index); - } - - public int ColCount - { - get - { - return ((Decal.Adapter.Wrappers.ListWrapper)myControl).ColCount; - } - } - - public int ScrollPosition - { - get - { - return ((Decal.Adapter.Wrappers.ListWrapper)myControl).ScrollPosition; - } - set - { - ((Decal.Adapter.Wrappers.ListWrapper)myControl).ScrollPosition = value; - } - } - - #endregion - - public class ListRow : IListRow - { - internal List myList; - internal int myRow; - internal ListRow(List l, int r) - { - myList = l; - myRow = r; - } - - - #region IListRow Members - - public IListCell this[int col] - { - get { return new ListCell(myList, myRow, col); } - } - - #endregion - } - - public class ListCell : IListCell - { - internal List myList; - internal int myRow; - internal int myCol; - public ListCell(List l, int r, int c) - { - myList = l; - myRow = r; - myCol = c; - } - - #region IListCell Members - - public void ResetColor() - { - Color = System.Drawing.Color.White; - } - - public System.Drawing.Color Color - { - get - { - return ((Decal.Adapter.Wrappers.ListWrapper)myList.myControl)[myRow][myCol].Color; - } - set - { - ((Decal.Adapter.Wrappers.ListWrapper)myList.myControl)[myRow][myCol].Color = value; - } - } - - public int Width - { - get - { - return ((Decal.Adapter.Wrappers.ListWrapper)myList.myControl)[myRow][myCol].Width; - } - set - { - ((Decal.Adapter.Wrappers.ListWrapper)myList.myControl)[myRow][myCol].Width = value; - } - } - - public object this[int subval] - { - get - { - return ((Decal.Adapter.Wrappers.ListWrapper)myList.myControl)[myRow][myCol][subval]; - } - set - { - ((Decal.Adapter.Wrappers.ListWrapper)myList.myControl)[myRow][myCol][subval] = value; - } - } - - #endregion - } - - } - -#if VVS_WRAPPERS_PUBLIC - public -#else - internal -#endif - class StaticText : Control, IStaticText - { - - #region IStaticText Members - - public string Text - { - get - { - return ((Decal.Adapter.Wrappers.StaticWrapper)myControl).Text; - } - set - { - ((Decal.Adapter.Wrappers.StaticWrapper)myControl).Text = value; - } - } - -#pragma warning disable 0067 - public event EventHandler Click; -#pragma warning restore 0067 - - #endregion - } - -#if VVS_WRAPPERS_PUBLIC - public -#else - internal -#endif - class Notebook : Control, INotebook - { - public override void Initialize() - { - base.Initialize(); - ((Decal.Adapter.Wrappers.NotebookWrapper)myControl).Change += new EventHandler(Notebook_Change); - } - - public override void Dispose() - { - base.Dispose(); - ((Decal.Adapter.Wrappers.NotebookWrapper)myControl).Change -= new EventHandler(Notebook_Change); - } - - void Notebook_Change(object sender, Decal.Adapter.IndexChangeEventArgs e) - { - if (Change != null) - Change(this, new MVIndexChangeEventArgs(this.Id, e.Index)); - } - - #region INotebook Members - - public event EventHandler Change; - - public int ActiveTab - { - get - { - return ((Decal.Adapter.Wrappers.NotebookWrapper)myControl).ActiveTab; - } - set - { - ((Decal.Adapter.Wrappers.NotebookWrapper)myControl).ActiveTab = value; - } - } - - #endregion - } - -#if VVS_WRAPPERS_PUBLIC - public -#else - internal -#endif - class ProgressBar : Control, IProgressBar - { - - #region IProgressBar Members - - public int Position - { - get - { - return ((Decal.Adapter.Wrappers.ProgressWrapper)myControl).Value; - } - set - { - ((Decal.Adapter.Wrappers.ProgressWrapper)myControl).Value = value; - } - } - - public int Value - { - get - { - return Position; - } - set - { - Position = value; - } - } - - public string PreText - { - get - { - return ((Decal.Adapter.Wrappers.ProgressWrapper)myControl).PreText; - } - set - { - ((Decal.Adapter.Wrappers.ProgressWrapper)myControl).PreText = value; - } - } - - public int MaxValue - { - get - { - return ((Decal.Adapter.Wrappers.ProgressWrapper)myControl).MaxValue; - } - set - { - ((Decal.Adapter.Wrappers.ProgressWrapper)myControl).MaxValue = value; - } - } - - #endregion - } - -#if VVS_WRAPPERS_PUBLIC - public -#else - internal -#endif - class ImageButton : Control, IImageButton - { - public override void Initialize() - { - base.Initialize(); - ((Decal.Adapter.Wrappers.ButtonWrapper)myControl).Click += new EventHandler(ImageButton_Click); - } - - public override void Dispose() - { - base.Dispose(); - ((Decal.Adapter.Wrappers.ButtonWrapper)myControl).Click -= new EventHandler(ImageButton_Click); - } - - void ImageButton_Click(object sender, Decal.Adapter.ControlEventArgs e) - { - if (Click != null) - Click(this, new MVControlEventArgs(this.Id)); - } - - - #region IImageButton Members - - public event EventHandler Click; - - public void SetImages(int unpressed, int pressed) - { - ((Decal.Adapter.Wrappers.ButtonWrapper)myControl).SetImages(unpressed, pressed); - } - - public void SetImages(int hmodule, int unpressed, int pressed) - { - ((Decal.Adapter.Wrappers.ButtonWrapper)myControl).SetImages(hmodule, unpressed, pressed); - } - - public int Background - { - set - { - ((Decal.Adapter.Wrappers.ButtonWrapper)myControl).Background = value; - } - } - - public System.Drawing.Color Matte - { - set - { - ((Decal.Adapter.Wrappers.ButtonWrapper)myControl).Matte = value; - } - } - - #endregion - } -} - diff --git a/MosswartMassacre/Wrapper_MyHuds.cs b/MosswartMassacre/Wrapper_MyHuds.cs deleted file mode 100644 index e2e097f..0000000 --- a/MosswartMassacre/Wrapper_MyHuds.cs +++ /dev/null @@ -1,1225 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -//File: Wrapper_MyHuds.cs -// -//Description: Contains MetaViewWrapper classes implementing Virindi View Service -// views. These classes are only compiled if the VVS_REFERENCED symbol is defined. -// -//References required: -// System.Drawing -// VirindiViewService (if VVS_REFERENCED is defined) -// -//This file is Copyright (c) 2010 VirindiPlugins -// -//Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -//The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -/////////////////////////////////////////////////////////////////////////////// - -#if VVS_REFERENCED - -using System; -using System.Collections.Generic; -using System.Text; -using VirindiViewService; - -#if METAVIEW_PUBLIC_NS -namespace MetaViewWrappers.VirindiViewServiceHudControls -#else -namespace MyClasses.MetaViewWrappers.VirindiViewServiceHudControls -#endif -{ -#if VVS_WRAPPERS_PUBLIC - public -#else - internal -#endif - class View : IView - { - HudView myView; - public HudView Underlying { get { return myView; } } - - #region IView Members - - public void Initialize(Decal.Adapter.Wrappers.PluginHost p, string pXML) - { - VirindiViewService.XMLParsers.Decal3XMLParser ps = new VirindiViewService.XMLParsers.Decal3XMLParser(); - ViewProperties iprop; - ControlGroup igroup; - ps.ParseFromResource(pXML, out iprop, out igroup); - myView = new VirindiViewService.HudView(iprop, igroup); - } - - public void InitializeRawXML(Decal.Adapter.Wrappers.PluginHost p, string pXML) - { - VirindiViewService.XMLParsers.Decal3XMLParser ps = new VirindiViewService.XMLParsers.Decal3XMLParser(); - ViewProperties iprop; - ControlGroup igroup; - ps.Parse(pXML, out iprop, out igroup); - myView = new VirindiViewService.HudView(iprop, igroup); - } - - public void Initialize(Decal.Adapter.Wrappers.PluginHost p, string pXML, string pWindowKey) - { - VirindiViewService.XMLParsers.Decal3XMLParser ps = new VirindiViewService.XMLParsers.Decal3XMLParser(); - ViewProperties iprop; - ControlGroup igroup; - ps.ParseFromResource(pXML, out iprop, out igroup); - myView = new VirindiViewService.HudView(iprop, igroup, pWindowKey); - } - - public void InitializeRawXML(Decal.Adapter.Wrappers.PluginHost p, string pXML, string pWindowKey) - { - VirindiViewService.XMLParsers.Decal3XMLParser ps = new VirindiViewService.XMLParsers.Decal3XMLParser(); - ViewProperties iprop; - ControlGroup igroup; - ps.Parse(pXML, out iprop, out igroup); - myView = new VirindiViewService.HudView(iprop, igroup, pWindowKey); - } - - public void SetIcon(int icon, int iconlibrary) - { - myView.Icon = ACImage.FromIconLibrary(icon, iconlibrary); - } - - public void SetIcon(int portalicon) - { - myView.Icon = portalicon; - } - - public string Title - { - get - { - return myView.Title; - } - set - { - myView.Title = value; - } - } - - public bool Visible - { - get - { - return myView.Visible; - } - set - { - myView.Visible = value; - } - } - - public bool Activated - { - get - { - return Visible; - } - set - { - Visible = value; - } - } - - public void Activate() - { - Visible = true; - } - - public void Deactivate() - { - Visible = false; - } - - public System.Drawing.Point Location - { - get - { - return myView.Location; - } - set - { - myView.Location = value; - } - } - - public System.Drawing.Size Size - { - get - { - return new System.Drawing.Size(myView.Width, myView.Height); - } - } - - public System.Drawing.Rectangle Position - { - get - { - return new System.Drawing.Rectangle(Location, Size); - } - set - { - Location = value.Location; - myView.ClientArea = value.Size; - } - } - -#if VVS_WRAPPERS_PUBLIC - internal -#else - public -#endif - ViewSystemSelector.eViewSystem ViewType { get { return ViewSystemSelector.eViewSystem.VirindiViewService; } } - Dictionary CreatedControlsByName = new Dictionary(); - - public IControl this[string id] - { - get - { - if (CreatedControlsByName.ContainsKey(id)) return CreatedControlsByName[id]; - - Control ret = null; - VirindiViewService.Controls.HudControl iret = myView[id]; - if (iret.GetType() == typeof(VirindiViewService.Controls.HudButton)) - ret = new Button(); - if (iret.GetType() == typeof(VirindiViewService.Controls.HudCheckBox)) - ret = new CheckBox(); - if (iret.GetType() == typeof(VirindiViewService.Controls.HudTextBox)) - ret = new TextBox(); - if (iret.GetType() == typeof(VirindiViewService.Controls.HudCombo)) - ret = new Combo(); - if (iret.GetType() == typeof(VirindiViewService.Controls.HudHSlider)) - ret = new Slider(); - if (iret.GetType() == typeof(VirindiViewService.Controls.HudList)) - ret = new List(); - if (iret.GetType() == typeof(VirindiViewService.Controls.HudStaticText)) - ret = new StaticText(); - if (iret.GetType() == typeof(VirindiViewService.Controls.HudTabView)) - ret = new Notebook(); - if (iret.GetType() == typeof(VirindiViewService.Controls.HudProgressBar)) - ret = new ProgressBar(); - if (iret.GetType() == typeof(VirindiViewService.Controls.HudImageButton)) - ret = new ImageButton(); - - if (ret == null) return null; - - ret.myControl = iret; - ret.myName = id; - ret.Initialize(); - allocatedcontrols.Add(ret); - CreatedControlsByName[id] = ret; - return ret; - } - } - - #endregion - - #region IDisposable Members - - bool disposed = false; - public void Dispose() - { - if (disposed) return; - disposed = true; - GC.SuppressFinalize(this); - - foreach (Control c in allocatedcontrols) - c.Dispose(); - - myView.Dispose(); - } - - #endregion - - List allocatedcontrols = new List(); - } - -#if VVS_WRAPPERS_PUBLIC - public -#else - internal -#endif - class Control : IControl - { - internal VirindiViewService.Controls.HudControl myControl; - internal string myName; - public VirindiViewService.Controls.HudControl Underlying { get { return myControl; } } - - public virtual void Initialize() - { - - } - - #region IControl Members - - public string Name - { - get { return myName; } - } - - public bool Visible - { - get { return myControl.Visible; } - set { myControl.Visible = value; } - } - - VirindiViewService.TooltipSystem.cTooltipInfo itooltipinfo = null; - public string TooltipText - { - get - { - if (itooltipinfo != null) - return itooltipinfo.Text; - else - return ""; - } - set - { - if (itooltipinfo != null) - { - VirindiViewService.TooltipSystem.RemoveTooltip(itooltipinfo); - itooltipinfo = null; - } - if (!String.IsNullOrEmpty(value)) - { - itooltipinfo = VirindiViewService.TooltipSystem.AssociateTooltip(myControl, value); - } - } - } - - public int Id - { - get - { - return myControl.XMLID; - } - } - - public System.Drawing.Rectangle LayoutPosition - { - get - { - //Relative to what?!??! - if (Underlying.Group.HeadControl == null) - return new System.Drawing.Rectangle(); - - if (Underlying.Group.HeadControl.Name == Underlying.Name) - return new System.Drawing.Rectangle(); - - VirindiViewService.Controls.HudControl myparent = Underlying.Group.ParentOf(Underlying.Name); - - if (myparent == null) - return new System.Drawing.Rectangle(); - - //Position only valid inside fixedlayouts - VirindiViewService.Controls.HudFixedLayout layoutparent = myparent as VirindiViewService.Controls.HudFixedLayout; - - if (layoutparent == null) - return new System.Drawing.Rectangle(); - - return layoutparent.GetControlRect(Underlying); - } - set - { - if (Underlying.Group.HeadControl == null) - return; - - if (Underlying.Group.HeadControl.Name == Underlying.Name) - return; - - VirindiViewService.Controls.HudControl myparent = Underlying.Group.ParentOf(Underlying.Name); - - if (myparent == null) - return; - - //Position only valid inside fixedlayouts - VirindiViewService.Controls.HudFixedLayout layoutparent = myparent as VirindiViewService.Controls.HudFixedLayout; - - if (layoutparent == null) - return; - - layoutparent.SetControlRect(Underlying, value); - } - } - - #endregion - - #region IDisposable Members - - bool disposed = false; - public virtual void Dispose() - { - if (disposed) return; - disposed = true; - - myControl.Dispose(); - } - - #endregion - } - -#if VVS_WRAPPERS_PUBLIC - public -#else - internal -#endif - class Button : Control, IButton - { - public override void Initialize() - { - base.Initialize(); - ((VirindiViewService.Controls.HudButton)myControl).MouseEvent += new EventHandler(Button_MouseEvent); - } - - public override void Dispose() - { - base.Dispose(); - ((VirindiViewService.Controls.HudButton)myControl).MouseEvent -= new EventHandler(Button_MouseEvent); - } - - void Button_MouseEvent(object sender, VirindiViewService.Controls.ControlMouseEventArgs e) - { - switch (e.EventType) - { - case VirindiViewService.Controls.ControlMouseEventArgs.MouseEventType.MouseHit: - if (Click != null) - Click(this, new MVControlEventArgs(this.Id)); - return; - case VirindiViewService.Controls.ControlMouseEventArgs.MouseEventType.MouseDown: - if (Hit != null) - Hit(this, null); - return; - } - } - - #region IButton Members - - public string Text - { - get - { - return ((VirindiViewService.Controls.HudButton)myControl).Text; - } - set - { - ((VirindiViewService.Controls.HudButton)myControl).Text = value; - } - } - - public System.Drawing.Color TextColor - { - get - { - return System.Drawing.Color.Black; - } - set - { - - } - } - - public event EventHandler Hit; - public event EventHandler Click; - - #endregion - } - -#if VVS_WRAPPERS_PUBLIC - public -#else - internal -#endif - class CheckBox : Control, ICheckBox - { - public override void Initialize() - { - base.Initialize(); - ((VirindiViewService.Controls.HudCheckBox)myControl).Change += new EventHandler(CheckBox_Change); - } - - public override void Dispose() - { - base.Dispose(); - ((VirindiViewService.Controls.HudCheckBox)myControl).Change -= new EventHandler(CheckBox_Change); - } - - void CheckBox_Change(object sender, EventArgs e) - { - if (Change != null) - Change(this, new MVCheckBoxChangeEventArgs(this.Id, Checked)); - if (Change_Old != null) - Change_Old(this, null); - } - - #region ICheckBox Members - - public string Text - { - get - { - return ((VirindiViewService.Controls.HudCheckBox)myControl).Text; - } - set - { - ((VirindiViewService.Controls.HudCheckBox)myControl).Text = value; - } - } - - public bool Checked - { - get - { - return ((VirindiViewService.Controls.HudCheckBox)myControl).Checked; - } - set - { - ((VirindiViewService.Controls.HudCheckBox)myControl).Checked = value; - } - } - - public event EventHandler Change; - public event EventHandler Change_Old; - - #endregion - } - -#if VVS_WRAPPERS_PUBLIC - public -#else - internal -#endif - class TextBox : Control, ITextBox - { - public override void Initialize() - { - base.Initialize(); - ((VirindiViewService.Controls.HudTextBox)myControl).Change += new EventHandler(TextBox_Change); - myControl.LostFocus += new EventHandler(myControl_LostFocus); - } - - public override void Dispose() - { - base.Dispose(); - ((VirindiViewService.Controls.HudTextBox)myControl).Change -= new EventHandler(TextBox_Change); - myControl.LostFocus -= new EventHandler(myControl_LostFocus); - } - - void TextBox_Change(object sender, EventArgs e) - { - if (Change != null) - Change(this, new MVTextBoxChangeEventArgs(this.Id, Text)); - if (Change_Old != null) - Change_Old(this, null); - } - - void myControl_LostFocus(object sender, EventArgs e) - { - if (!myControl.HasFocus) return; - - if (End != null) - End(this, new MVTextBoxEndEventArgs(this.Id, true)); - } - - #region ITextBox Members - - public string Text - { - get - { - return ((VirindiViewService.Controls.HudTextBox)myControl).Text; - } - set - { - ((VirindiViewService.Controls.HudTextBox)myControl).Text = value; - } - } - - public int Caret - { - get - { - return 0; - } - set - { - - } - } - - public event EventHandler Change; - public event EventHandler Change_Old; - public event EventHandler End; - - #endregion - } - -#if VVS_WRAPPERS_PUBLIC - public -#else - internal -#endif - class Combo : Control, ICombo - { - List iData = new List(); - - public Combo() - { - //TODO: add data values from the xml - } - - public class ComboIndexer : IComboIndexer - { - Combo underlying; - internal ComboIndexer(Combo c) - { - underlying = c; - } - - #region IComboIndexer Members - - public string this[int index] - { - get - { - return ((VirindiViewService.Controls.HudStaticText)(((VirindiViewService.Controls.HudCombo)underlying.myControl)[index])).Text; - } - set - { - ((VirindiViewService.Controls.HudStaticText)(((VirindiViewService.Controls.HudCombo)underlying.myControl)[index])).Text = value; - } - } - - #endregion - } - - public class ComboDataIndexer : IComboDataIndexer - { - Combo underlying; - internal ComboDataIndexer(Combo c) - { - underlying = c; - } - - #region IComboIndexer Members - - public object this[int index] - { - get - { - return underlying.iData[index]; - } - set - { - underlying.iData[index] = value; - } - } - - #endregion - } - - public override void Initialize() - { - base.Initialize(); - ((VirindiViewService.Controls.HudCombo)myControl).Change += new EventHandler(Combo_Change); - } - - public override void Dispose() - { - base.Dispose(); - ((VirindiViewService.Controls.HudCombo)myControl).Change -= new EventHandler(Combo_Change); - } - - void Combo_Change(object sender, EventArgs e) - { - if (Change != null) - Change(this, new MVIndexChangeEventArgs(this.Id, Selected)); - if (Change_Old != null) - Change_Old(this, null); - } - - #region ICombo Members - - public IComboIndexer Text - { - get { return new ComboIndexer(this); } - } - - public IComboDataIndexer Data - { - get { return new ComboDataIndexer(this); } - } - - public int Count - { - get { return ((VirindiViewService.Controls.HudCombo)myControl).Count; } - } - - public int Selected - { - get - { - return ((VirindiViewService.Controls.HudCombo)myControl).Current; - } - set - { - ((VirindiViewService.Controls.HudCombo)myControl).Current = value; - } - } - - public event EventHandler Change; - public event EventHandler Change_Old; - - public void Add(string text) - { - ((VirindiViewService.Controls.HudCombo)myControl).AddItem(text, null); - iData.Add(null); - } - - public void Add(string text, object obj) - { - ((VirindiViewService.Controls.HudCombo)myControl).AddItem(text, null); - iData.Add(obj); - } - - public void Insert(int index, string text) - { - ((VirindiViewService.Controls.HudCombo)myControl).InsertItem(index, text, null); - iData.Insert(index, null); - } - - public void RemoveAt(int index) - { - ((VirindiViewService.Controls.HudCombo)myControl).DeleteItem(index); - iData.RemoveAt(index); - } - - public void Remove(int index) - { - RemoveAt(index); - } - - public void Clear() - { - ((VirindiViewService.Controls.HudCombo)myControl).Clear(); - iData.Clear(); - } - - #endregion - } - -#if VVS_WRAPPERS_PUBLIC - public -#else - internal -#endif - class Slider : Control, ISlider - { - public override void Initialize() - { - base.Initialize(); - ((VirindiViewService.Controls.HudHSlider)myControl).Changed += new VirindiViewService.Controls.LinearPositionControl.delScrollChanged(Slider_Changed); - } - - public override void Dispose() - { - base.Dispose(); - ((VirindiViewService.Controls.HudHSlider)myControl).Changed -= new VirindiViewService.Controls.LinearPositionControl.delScrollChanged(Slider_Changed); - } - - void Slider_Changed(int min, int max, int pos) - { - if (Change != null) - Change(this, new MVIndexChangeEventArgs(this.Id, pos)); - if (Change_Old != null) - Change_Old(this, null); - } - - #region ISlider Members - - public int Position - { - get - { - return ((VirindiViewService.Controls.HudHSlider)myControl).Position; - } - set - { - ((VirindiViewService.Controls.HudHSlider)myControl).Position = value; - } - } - - public event EventHandler Change; - public event EventHandler Change_Old; - - public int Maximum - { - get - { - return ((VirindiViewService.Controls.HudHSlider)myControl).Max; - } - set - { - ((VirindiViewService.Controls.HudHSlider)myControl).Max = value; - } - } - public int Minimum - { - get - { - return ((VirindiViewService.Controls.HudHSlider)myControl).Min; - } - set - { - ((VirindiViewService.Controls.HudHSlider)myControl).Min = value; - } - } - - #endregion - } - -#if VVS_WRAPPERS_PUBLIC - public -#else - internal -#endif - class List : Control, IList - { - public override void Initialize() - { - base.Initialize(); - ((VirindiViewService.Controls.HudList)myControl).Click += new VirindiViewService.Controls.HudList.delClickedControl(List_Click); - } - - public override void Dispose() - { - base.Dispose(); - ((VirindiViewService.Controls.HudList)myControl).Click -= new VirindiViewService.Controls.HudList.delClickedControl(List_Click); - } - - void List_Click(object sender, int row, int col) - { - if (Click != null) - Click(this, row, col); - if (Selected != null) - Selected(this, new MVListSelectEventArgs(this.Id, row, col)); - } - - public class ListRow : IListRow - { - List myList; - int myRow; - internal ListRow(int row, List l) - { - myList = l; - myRow = row; - } - - #region IListRow Members - - public IListCell this[int col] - { - get { return new ListCell(myRow, col, myList); } - } - - #endregion - } - public class ListCell : IListCell - { - List myList; - int myRow; - int myCol; - internal ListCell(int row, int col, List l) - { - myRow = row; - myCol = col; - myList = l; - } - - #region IListCell Members - - public void ResetColor() - { - ((VirindiViewService.Controls.HudStaticText)(((VirindiViewService.Controls.HudList)myList.myControl)[myRow][myCol])).ResetTextColor(); - } - - public System.Drawing.Color Color - { - get - { - return ((VirindiViewService.Controls.HudStaticText)(((VirindiViewService.Controls.HudList)myList.myControl)[myRow][myCol])).TextColor; - } - set - { - ((VirindiViewService.Controls.HudStaticText)(((VirindiViewService.Controls.HudList)myList.myControl)[myRow][myCol])).TextColor = value; - } - } - - public int Width - { - get - { - return ((VirindiViewService.Controls.HudStaticText)(((VirindiViewService.Controls.HudList)myList.myControl)[myRow][myCol])).ClipRegion.Width; - } - set - { - throw new Exception("The method or operation is not implemented."); - } - } - - public object this[int subval] - { - get - { - VirindiViewService.Controls.HudControl c = ((VirindiViewService.Controls.HudList)myList.myControl)[myRow][myCol]; - if (subval == 0) - { - if (c.GetType() == typeof(VirindiViewService.Controls.HudStaticText)) - return ((VirindiViewService.Controls.HudStaticText)c).Text; - if (c.GetType() == typeof(VirindiViewService.Controls.HudCheckBox)) - return ((VirindiViewService.Controls.HudCheckBox)c).Checked; - } - else if (subval == 1) - { - if (c.GetType() == typeof(VirindiViewService.Controls.HudPictureBox)) - return ((VirindiViewService.Controls.HudPictureBox)c).Image.PortalImageID; - } - return null; - } - set - { - VirindiViewService.Controls.HudControl c = ((VirindiViewService.Controls.HudList)myList.myControl)[myRow][myCol]; - if (subval == 0) - { - if (c.GetType() == typeof(VirindiViewService.Controls.HudStaticText)) - ((VirindiViewService.Controls.HudStaticText)c).Text = (string)value; - if (c.GetType() == typeof(VirindiViewService.Controls.HudCheckBox)) - ((VirindiViewService.Controls.HudCheckBox)c).Checked = (bool)value; - } - else if (subval == 1) - { - if (c.GetType() == typeof(VirindiViewService.Controls.HudPictureBox)) - ((VirindiViewService.Controls.HudPictureBox)c).Image = (int)value; - } - } - } - - #endregion - } - - #region IList Members - - public event dClickedList Click; - public event EventHandler Selected; - - public void Clear() - { - ((VirindiViewService.Controls.HudList)myControl).ClearRows(); - } - - public IListRow this[int row] - { - get { return new ListRow(row, this); } - } - - public IListRow AddRow() - { - ((VirindiViewService.Controls.HudList)myControl).AddRow(); - return new ListRow(((VirindiViewService.Controls.HudList)myControl).RowCount - 1, this); - } - - public IListRow Add() - { - return AddRow(); - } - - public IListRow InsertRow(int pos) - { - ((VirindiViewService.Controls.HudList)myControl).InsertRow(pos); - return new ListRow(pos, this); - } - - public IListRow Insert(int pos) - { - return InsertRow(pos); - } - - public int RowCount - { - get { return ((VirindiViewService.Controls.HudList)myControl).RowCount; } - } - - public void RemoveRow(int index) - { - ((VirindiViewService.Controls.HudList)myControl).RemoveRow(index); - } - - public void Delete(int index) - { - RemoveRow(index); - } - - public int ColCount - { - get - { - return ((VirindiViewService.Controls.HudList)myControl).ColumnCount; - } - } - - public int ScrollPosition - { - get - { - return ((VirindiViewService.Controls.HudList)myControl).ScrollPosition; - } - set - { - ((VirindiViewService.Controls.HudList)myControl).ScrollPosition = value; - } - } - - #endregion - } - -#if VVS_WRAPPERS_PUBLIC - public -#else - internal -#endif - class StaticText : Control, IStaticText - { - public override void Initialize() - { - base.Initialize(); - //((VirindiViewService.Controls.HudStaticText)myControl) - } - - public override void Dispose() - { - base.Dispose(); - } - - #region IStaticText Members - - public string Text - { - get - { - return ((VirindiViewService.Controls.HudStaticText)myControl).Text; - } - set - { - ((VirindiViewService.Controls.HudStaticText)myControl).Text = value; - } - } - -#pragma warning disable 0067 - public event EventHandler Click; -#pragma warning restore 0067 - - #endregion - } - -#if VVS_WRAPPERS_PUBLIC - public -#else - internal -#endif - class Notebook : Control, INotebook - { - public override void Initialize() - { - base.Initialize(); - ((VirindiViewService.Controls.HudTabView)myControl).OpenTabChange += new EventHandler(Notebook_OpenTabChange); - } - - public override void Dispose() - { - ((VirindiViewService.Controls.HudTabView)myControl).OpenTabChange -= new EventHandler(Notebook_OpenTabChange); - base.Dispose(); - } - - void Notebook_OpenTabChange(object sender, EventArgs e) - { - if (Change != null) - Change(this, new MVIndexChangeEventArgs(this.Id, ActiveTab)); - } - - #region INotebook Members - - public event EventHandler Change; - - public int ActiveTab - { - get - { - return ((VirindiViewService.Controls.HudTabView)myControl).CurrentTab; - } - set - { - ((VirindiViewService.Controls.HudTabView)myControl).CurrentTab = value; - ((VirindiViewService.Controls.HudTabView)myControl).Invalidate(); - } - } - - #endregion - } - -#if VVS_WRAPPERS_PUBLIC - public -#else - internal -#endif - class ProgressBar : Control, IProgressBar - { - - #region IProgressBar Members - - public int Position - { - get - { - return ((VirindiViewService.Controls.HudProgressBar)myControl).Position; - } - set - { - ((VirindiViewService.Controls.HudProgressBar)myControl).Position = value; - } - } - - public int Value - { - get - { - return Position; - } - set - { - Position = value; - } - } - - public string PreText - { - get - { - return ((VirindiViewService.Controls.HudProgressBar)myControl).PreText; - } - set - { - ((VirindiViewService.Controls.HudProgressBar)myControl).PreText = value; - } - } - - - public int MaxValue - { - get - { - return ((VirindiViewService.Controls.HudProgressBar)myControl).Max; - } - set - { - ((VirindiViewService.Controls.HudProgressBar)myControl).Max = value; - } - } - - #endregion - } - -#if VVS_WRAPPERS_PUBLIC - public -#else - internal -#endif - class ImageButton : Control, IImageButton - { - public override void Initialize() - { - base.Initialize(); - myControl.MouseEvent += new EventHandler(Button_MouseEvent); - } - - public override void Dispose() - { - base.Dispose(); - myControl.MouseEvent -= new EventHandler(Button_MouseEvent); - } - - void Button_MouseEvent(object sender, VirindiViewService.Controls.ControlMouseEventArgs e) - { - switch (e.EventType) - { - case VirindiViewService.Controls.ControlMouseEventArgs.MouseEventType.MouseHit: - if (Click != null) - Click(this, new MVControlEventArgs(this.Id)); - return; - } - } - - #region IImageButton Members - - public event EventHandler Click; - - public void SetImages(int unpressed, int pressed) - { - ACImage upimg; - if (!VirindiViewService.Service.PortalBitmapExists(unpressed | 0x06000000)) - upimg = new ACImage(); - else - upimg = new ACImage(unpressed, ACImage.eACImageDrawOptions.DrawStretch); - - ACImage pimg; - if (!VirindiViewService.Service.PortalBitmapExists(pressed | 0x06000000)) - pimg = new ACImage(); - else - pimg = new ACImage(pressed, ACImage.eACImageDrawOptions.DrawStretch); - - ((VirindiViewService.Controls.HudImageButton)myControl).Image_Up = upimg; - ((VirindiViewService.Controls.HudImageButton)myControl).Image_Up_Pressing = pimg; - } - - public void SetImages(int hmodule, int unpressed, int pressed) - { - ((VirindiViewService.Controls.HudImageButton)myControl).Image_Up = ACImage.FromIconLibrary(unpressed, hmodule); - ((VirindiViewService.Controls.HudImageButton)myControl).Image_Up_Pressing = ACImage.FromIconLibrary(pressed, hmodule); - } - - public int Background - { - set - { - ((VirindiViewService.Controls.HudImageButton)myControl).Image_Background2 = new ACImage(value, ACImage.eACImageDrawOptions.DrawStretch); - } - } - - public System.Drawing.Color Matte - { - set - { - ((VirindiViewService.Controls.HudImageButton)myControl).Image_Background = new ACImage(value); - } - } - - #endregion - } -} - -#else -#warning VVS_REFERENCED not defined, MetaViewWrappers for VVS will not be available. -#endif \ No newline at end of file diff --git a/MosswartMassacre/Wrapper_WireupHelper.cs b/MosswartMassacre/Wrapper_WireupHelper.cs deleted file mode 100644 index 63deeaf..0000000 --- a/MosswartMassacre/Wrapper_WireupHelper.cs +++ /dev/null @@ -1,329 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -//File: Wrapper_WireupHelper.cs -// -//Description: A helper utility that emulates Decal.Adapter's automagic view -// creation and control/event wireup with the MetaViewWrappers. A separate set -// of attributes is used. -// -//References required: -// Wrapper.cs -// -//This file is Copyright (c) 2010 VirindiPlugins -// -//Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -//The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -/////////////////////////////////////////////////////////////////////////////// - -using System; -using System.Collections.Generic; -using System.Text; -using System.Reflection; - -#if METAVIEW_PUBLIC_NS -namespace MetaViewWrappers -#else -namespace MyClasses.MetaViewWrappers -#endif -{ - #region Attribute Definitions - - [AttributeUsage(AttributeTargets.Class)] -#if VVS_WRAPPERS_PUBLIC - public -#else - internal -#endif - sealed class MVWireUpControlEventsAttribute : Attribute - { - public MVWireUpControlEventsAttribute() { } - } - - [AttributeUsage(AttributeTargets.Field)] -#if VVS_WRAPPERS_PUBLIC - public -#else - internal -#endif - sealed class MVControlReferenceAttribute : Attribute - { - string ctrl; - - // Summary: - // Construct a new ControlReference - // - // Parameters: - // control: - // Control to reference - public MVControlReferenceAttribute(string control) - { - ctrl = control; - } - - // Summary: - // The Control Name - public string Control - { - get - { - return ctrl; - } - } - } - - [AttributeUsage(AttributeTargets.Field)] -#if VVS_WRAPPERS_PUBLIC - public -#else - internal -#endif - sealed class MVControlReferenceArrayAttribute : Attribute - { - private System.Collections.ObjectModel.Collection myControls; - - /// - /// Constructs a new ControlReference array - /// - /// Names of the controls to put in the array - public MVControlReferenceArrayAttribute(params string[] controls) - : base() - { - this.myControls = new System.Collections.ObjectModel.Collection(controls); - } - - /// - /// Control collection - /// - public System.Collections.ObjectModel.Collection Controls - { - get - { - return this.myControls; - } - } - } - - [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] -#if VVS_WRAPPERS_PUBLIC - public -#else - internal -#endif - sealed class MVViewAttribute : Attribute - { - string res; - - // Summary: - // Constructs a new view from the specified resource - // - // Parameters: - // Resource: - // Embedded resource path - public MVViewAttribute(string resource) - { - res = resource; - } - - // Summary: - // The resource to load - public string Resource - { - get - { - return res; - } - } - } - - [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] -#if VVS_WRAPPERS_PUBLIC - public -#else - internal -#endif - sealed class MVControlEventAttribute : Attribute - { - string c; - string e; - // Summary: - // Constructs the ControlEvent - // - // Parameters: - // control: - // Control Name - // - // controlEvent: - // Event to Wire - public MVControlEventAttribute(string control, string eventName) - { - c = control; - e = eventName; - } - - // Summary: - // Control Name - public string Control - { - get - { - return c; - } - } - - // - // Summary: - // Event to Wire - public string EventName - { - get - { - return e; - } - } - } - - #endregion Attribute Definitions - -#if VVS_WRAPPERS_PUBLIC - public -#else - internal -#endif - static class MVWireupHelper - { - private class ViewObjectInfo - { - public List Views = new List(); - } - static Dictionary VInfo = new Dictionary(); - - public static MyClasses.MetaViewWrappers.IView GetDefaultView(object ViewObj) - { - if (!VInfo.ContainsKey(ViewObj)) - return null; - if (VInfo[ViewObj].Views.Count == 0) - return null; - return VInfo[ViewObj].Views[0]; - } - - public static void WireupStart(object ViewObj, Decal.Adapter.Wrappers.PluginHost Host) - { - if (VInfo.ContainsKey(ViewObj)) - WireupEnd(ViewObj); - ViewObjectInfo info = new ViewObjectInfo(); - VInfo[ViewObj] = info; - - Type ObjType = ViewObj.GetType(); - - //Start views - object[] viewattrs = ObjType.GetCustomAttributes(typeof(MVViewAttribute), true); - foreach (MVViewAttribute a in viewattrs) - { - info.Views.Add(MyClasses.MetaViewWrappers.ViewSystemSelector.CreateViewResource(Host, a.Resource)); - } - - //Wire up control references - foreach (FieldInfo fi in ObjType.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy)) - { - if (Attribute.IsDefined(fi, typeof(MVControlReferenceAttribute))) - { - MVControlReferenceAttribute attr = (MVControlReferenceAttribute)Attribute.GetCustomAttribute(fi, typeof(MVControlReferenceAttribute)); - MetaViewWrappers.IControl mycontrol = null; - - //Try each view - foreach (MyClasses.MetaViewWrappers.IView v in info.Views) - { - try - { - mycontrol = v[attr.Control]; - } - catch { } - if (mycontrol != null) - break; - } - - if (mycontrol == null) - throw new Exception("Invalid control reference \"" + attr.Control + "\""); - - if (!fi.FieldType.IsAssignableFrom(mycontrol.GetType())) - throw new Exception("Control reference \"" + attr.Control + "\" is of wrong type"); - - fi.SetValue(ViewObj, mycontrol); - } - else if (Attribute.IsDefined(fi, typeof(MVControlReferenceArrayAttribute))) - { - MVControlReferenceArrayAttribute attr = (MVControlReferenceArrayAttribute)Attribute.GetCustomAttribute(fi, typeof(MVControlReferenceArrayAttribute)); - - //Only do the first view - if (info.Views.Count == 0) - throw new Exception("No views to which a control reference can attach"); - - Array controls = Array.CreateInstance(fi.FieldType.GetElementType(), attr.Controls.Count); - - IView view = info.Views[0]; - for (int i = 0; i < attr.Controls.Count; ++i) - { - controls.SetValue(view[attr.Controls[i]], i); - } - - fi.SetValue(ViewObj, controls); - } - } - - //Wire up events - foreach (MethodInfo mi in ObjType.GetMethods(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy)) - { - if (!Attribute.IsDefined(mi, typeof(MVControlEventAttribute))) - continue; - Attribute[] attrs = Attribute.GetCustomAttributes(mi, typeof(MVControlEventAttribute)); - - foreach (MVControlEventAttribute attr in attrs) - { - MetaViewWrappers.IControl mycontrol = null; - //Try each view - foreach (MyClasses.MetaViewWrappers.IView v in info.Views) - { - try - { - mycontrol = v[attr.Control]; - } - catch { } - if (mycontrol != null) - break; - } - - if (mycontrol == null) - throw new Exception("Invalid control reference \"" + attr.Control + "\""); - - EventInfo ei = mycontrol.GetType().GetEvent(attr.EventName); - ei.AddEventHandler(mycontrol, Delegate.CreateDelegate(ei.EventHandlerType, ViewObj, mi.Name)); - } - } - } - - public static void WireupEnd(object ViewObj) - { - if (!VInfo.ContainsKey(ViewObj)) - return; - - foreach (MyClasses.MetaViewWrappers.IView v in VInfo[ViewObj].Views) - v.Dispose(); - - VInfo.Remove(ViewObj); - } - } -} \ No newline at end of file diff --git a/README.md b/README.md index 1b74fc4..c006689 100644 --- a/README.md +++ b/README.md @@ -1,90 +1,220 @@ -# Mossy Plugins +# MosswartMassacre - Advanced DECAL Plugin for Asheron's Call -A collection of DECAL plugins for Asheron's Call, providing utility overlays and automation features. +> **Status**: Production Ready | VVS Direct Integration | Navigation Visualization Complete - ## Contents - - `mossy.sln`: Visual Studio solution containing both projects. - - `GearCycler/`: Simple plugin with a UI button to cycle gear (placeholder behavior). - - `MosswartMassacre/`: Advanced plugin tracking monster kills, rare discoveries, and offering HTTP/telemetry features. - - `packages/`: Vendored NuGet packages (Newtonsoft.Json, YamlDotNet). +A comprehensive DECAL plugin for Asheron's Call that tracks monster kills, rare item discoveries, and provides advanced navigation route visualization with 3D rendering. - ## Prerequisites - - Windows with .NET Framework 4.8 - - Visual Studio 2017+ (MSBuild Tools 15.0) or equivalent MSBuild environment - - DECAL Adapter installed for Asheron's Call - - VirindiViewService (included in each project's `lib/` folder) +## 🚀 Features - ## Setup & Build - 1. Clone this repository. - 2. Ensure the DECAL and Virindi DLLs are present under `MosswartMassacre/lib/` and referenced by each project. - 3. Restore NuGet packages if needed (`nuget restore mossy.sln`). - 4. Open `mossy.sln` in Visual Studio and build the solution. - 5. The output DLLs will be in each project’s `bin/Debug/` or `bin/Release/` folder. - 6. Deploy the plugin DLLs (and any required XML or YAML files) to your DECAL plugin directory. +### Core Functionality +- **Kill Tracking**: Real-time monster kill counting with rate calculations (kills/5min, kills/hour) +- **Rare Item Discovery**: Automatic rare detection and counter with optional meta state control +- **Statistics Dashboard**: Detailed session statistics with best hourly performance tracking +- **Multi-System Integration**: WebSocket streaming, HTTP command server, and telemetry support - ## GearCycler - A minimal plugin demonstrating a VirindiViewService-based UI. - - UI layout: `GearCycler/ViewXML/mainView.xml`. - - Core logic in `GearCycler/GearCore.cs`. - - On button click, it logs a chat message; extend the `btnCycle.Hit` handler to add gear-cycling logic. +### 🗺️ Navigation Visualization +**Advanced VTank route visualization with 3D rendering capabilities** +- **3D Route Display**: Renders VTank .nav files as red lines in the game world +- **Route Comparison**: Side-by-side visualization with UtilityBelt's active navigation +- **Full Format Support**: All VTank nav types (Circular, Linear, Target, Once) and waypoint types +- **Auto-Discovery**: Automatically detects VTank installation and scans for .nav files +- **Performance Optimized**: Smart rendering limits and memory management - ## MosswartMassacre - Tracks monster kills and rare drops, with multiple utility features including navigation route visualization. +### 🎛️ User Interface +**Modern tabbed interface using direct VirindiViewService integration** +- **Main Tab**: Live kill stats, rare counts, elapsed time, and status indicators +- **Settings Tab**: Plugin configuration with real-time updates +- **Statistics Tab**: Enhanced analytics and session management +- **Navigation Tab**: Route selection, visualization controls, and status display - ### Features - - **Kill Tracking**: Counts total kills and computes rates (kills/5 min, kills/hour). - - **Rare Discoveries**: Increments rare count and can automatically set rare meta state. - - **Navigation Visualization** ✅ **NEW**: Visualize VTank navigation routes in 3D with route comparison capabilities. - - **Tabbed UI Interface**: Enhanced interface with Main, Settings, Statistics, and Navigation tabs. - - **Command Interface** (`/mm` commands): - - `/mm help` : Show available commands. - - `/mm report` : Display current stats in chat. - - `/mm loc` : Show current map coordinates. - - `/mm reset` : Reset kill counters and timers. - - `/mm meta` : Toggle automatic rare meta state. - - `/mm http ` : Start/stop local HTTP command server (port 8085). - - `/mm remotecommands ` : Listen for remote commands from your allegiance chat. - - `/mm telemetry ` : Enable/disable periodic telemetry streaming. +## 📥 Installation - ### HTTP Command Server - - Listens on `http://localhost:8085/`. - - Accepts POST data: `target=&command=`, then sends a /tell and executes the command. +### Prerequisites +- Windows with .NET Framework 4.8 +- Asheron's Call with DECAL Adapter installed +- VirindiViewService (included in lib/ folder) - ### Navigation Visualization ✅ NEW - - **VTank Integration**: Automatically detects VTank installation and loads .nav files. - - **3D Route Display**: Shows navigation routes as red lines in the game world. - - **Route Comparison**: Visualize different routes alongside UtilityBelt's active navigation. - - **Supported Formats**: All VTank nav types (Circular, Linear, Target, Once) and waypoint types. - - **Usage**: Enable in Navigation tab, select route from dropdown, click "Load Route". +### Quick Setup +1. Download the latest release from the releases page +2. Extract to your DECAL plugins directory +3. Restart DECAL and enable the plugin +4. Configure settings through the in-game UI - ### Configuration - - Per-character YAML config stored at `/.yaml`. - - Settings include: - - `remote_commands_enabled` - - `rare_meta_enabled` - - `http_server_enabled` - - `telemetry_enabled` - - `char_tag` - - `vtank_profiles_path` ✅ **NEW**: Custom VTank profiles directory - - Config is auto-generated on first run; modify it or use UI/commands to update. +### Building from Source +```bash +# Clone the repository +git clone [repository-url] +cd MosswartMassacre - ### Telemetry - - Periodically posts JSON snapshots of position and stats to a configurable endpoint. - - Configure `Endpoint`, `SharedSecret`, and `IntervalSec` in `Telemetry.cs`. +# Restore packages and build +nuget restore packages.config +msbuild MosswartMassacre.csproj /p:Configuration=Release /p:Platform=AnyCPU +``` - ## Dependencies - - Decal.Adapter (v2.9.8.3) - - Decal.Interop.Core & Decal.Interop.Inject - - Decal.Interop.D3DService ✅ **NEW**: For 3D navigation visualization - - VirindiViewService - - Newtonsoft.Json (v13.0.3) - - YamlDotNet (v16.3.0) +## 🎮 Usage - ## Contributing - 1. Fork the repository. - 2. Create a feature branch. - 3. Commit your changes and ensure the solution builds. - 4. Submit a pull request with a description of your changes. +### Basic Commands +Access all features through the `/mm` command interface: - -- - _This README provides a high-level overview to get up and running quickly._ \ No newline at end of file +``` +/mm help - Show available commands +/mm report - Display current kill statistics +/mm loc - Show current map coordinates +/mm reset - Reset kill counters and timers +/mm meta - Toggle automatic rare meta state +/mm http - Control HTTP command server (port 8085) +/mm telemetry - Control telemetry streaming +``` + +### Navigation Visualization +1. **Enable**: Check "Enable Navigation Visualization" in Navigation tab +2. **Configure**: Set VTank profiles path in Settings (auto-detected) +3. **Select Route**: Choose from dropdown and click "Load Route" +4. **View**: Red route lines appear in 3D game world + +### Configuration +Settings are stored per-character in YAML format at `/.yaml`: + +```yaml +rare_meta_enabled: true +remote_commands_enabled: false +http_server_enabled: false +websocket_enabled: true +telemetry_enabled: false +char_tag: "default" +vtank_profiles_path: "C:\\Games\\VirindiPlugins\\VirindiTank\\" +main_window_x: 100 +main_window_y: 100 +``` + +## 🏗️ Architecture + +### Core Components +- **PluginCore.cs**: Main entry point and event coordination +- **PluginSettings.cs**: YAML-based per-character configuration +- **Views/VVSTabbedMainView.cs**: Main tabbed UI with direct VVS integration +- **Views/VVSBaseView.cs**: Base class for VVS-based views + +### Navigation System +- **NavRoute.cs**: VTank .nav file parser and 3D renderer +- **NavVisualization.cs**: Route management and file discovery +- **Registry Integration**: Automatic VTank directory detection + +### Communication Systems +- **WebSocket.cs**: Real-time data streaming to external services +- **HttpCommandServer.cs**: Local HTTP API for remote control +- **Telemetry.cs**: Periodic statistics reporting + +### Game Integration +- **VtankControl.cs**: vTank automation interface +- **MossyInventory.cs**: Inventory monitoring and rare detection +- **Utils.cs**: Game coordinate systems and utility functions + +## 🔧 Technical Details + +### Dependencies +- **DECAL Framework**: Core plugin system (Decal.Adapter, Decal.Interop.Core, Decal.Interop.D3DService) +- **VirindiViewService**: UI framework for game overlays +- **Newtonsoft.Json**: JSON serialization for APIs +- **YamlDotNet**: Configuration file management + +### Build Configuration +- **Target**: .NET Framework 4.8, x86 platform +- **Architecture**: Direct VVS integration (no wrapper abstraction) +- **Features**: Unsafe blocks enabled for P/Invoke operations + +### Navigation File Format Support +**Complete VTank .nav format compatibility:** +- **Nav Types**: Circular (1), Linear (0/2), Target (3), Once (4) +- **Waypoint Types**: Point, Portal, Recall, Pause, ChatCommand, OpenVendor, Portal2, UseNPC, Checkpoint, Jump +- **Performance**: Optimized for routes up to 10,000 waypoints with 500-segment rendering limit + +## 🔌 API Integration + +### HTTP Command Server +```bash +# Enable server +curl -X POST http://localhost:8085/ -d "target=PlayerName&command=report" + +# Available endpoints +POST / - Execute command for target player +``` + +### WebSocket Streaming +Real-time data streaming to `wss://overlord.snakedesert.se/websocket/` including: +- Monster spawn/despawn events +- Chat messages and rare discoveries +- Player position and statistics +- Session-based authentication with SharedSecret + +### Telemetry Data +Periodic JSON snapshots posted to configurable endpoints: +```json +{ + "timestamp": "2024-12-19T10:30:00Z", + "character": "PlayerName", + "position": {"x": 59.2, "y": -28.7, "z": 0.05}, + "stats": {"kills": 150, "rares": 3, "session_time": "02:15:30"} +} +``` + +## 🛠️ Development + +### Project Structure +``` +MosswartMassacre/ +├── Views/ # VVS-based UI components +│ ├── VVSBaseView.cs # Base view foundation +│ └── VVSTabbedMainView.cs # Main tabbed interface +├── ViewXML/ # UI layout definitions +│ └── mainViewTabbed.xml # Current layout +├── NavRoute.cs # Navigation file parser +├── NavVisualization.cs # Route visualization manager +├── PluginCore.cs # Main plugin logic +├── PluginSettings.cs # Configuration management +└── lib/ # External dependencies +``` + +### Development Environment +- **IDE**: Visual Studio 2017+ or VS Code with C# extension +- **Tools**: MSBuild, NuGet Package Manager +- **Testing**: In-game with Asheron's Call client and DECAL + +### Contributing +1. Fork the repository +2. Create feature branch (`git checkout -b feature/amazing-feature`) +3. Commit changes (`git commit -m 'Add amazing feature'`) +4. Push to branch (`git push origin feature/amazing-feature`) +5. Open a Pull Request + +## 📚 Related Documentation + +- **CLAUDE.md**: Claude AI development guidance and build commands +- **Development History**: Successful VVS migration completed, wrapper system removed +- **Architecture Evolution**: Migrated from wrapper-based to direct VVS integration + +## 📄 License + +This project is licensed under the MIT License - see the LICENSE file for details. + +## 🎯 Roadmap + +### Completed ✅ +- [x] VVS Direct Integration Migration +- [x] Navigation Visualization System +- [x] Tabbed UI Interface +- [x] WebSocket Streaming +- [x] HTTP Command API +- [x] Telemetry System +- [x] Architecture Cleanup (Phase 3) + +### Future Enhancements +- [ ] Multiple route visualization +- [ ] Route analysis and optimization tools +- [ ] Enhanced UI controls and themes +- [ ] Plugin integration marketplace +- [ ] Advanced statistics and reporting + +--- + +*Built with ❤️ for the Asheron's Call community* \ No newline at end of file