Phase 5: Extract QuestStreamingService and introduce IGameStats
- Extract QuestStreamingService.cs from PluginCore (timer, IsHighPriorityQuest, FormatCountdown) - Create IGameStats interface for WebSocket telemetry decoupling - PluginCore implements IGameStats, WebSocket.BuildPayloadJson reads from IGameStats - WebSocket.cs no longer references PluginCore directly - Update queststatus command to use QuestStreamingService - Static bridge properties remain for VVSTabbedMainView compatibility Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
f9264f2767
commit
0713e96a99
6 changed files with 192 additions and 142 deletions
19
MosswartMassacre/IGameStats.cs
Normal file
19
MosswartMassacre/IGameStats.cs
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace MosswartMassacre
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Provides game statistics for WebSocket telemetry payloads.
|
||||||
|
/// Replaces direct static field access on PluginCore.
|
||||||
|
/// </summary>
|
||||||
|
public interface IGameStats
|
||||||
|
{
|
||||||
|
int TotalKills { get; }
|
||||||
|
double KillsPerHour { get; }
|
||||||
|
int SessionDeaths { get; }
|
||||||
|
int TotalDeaths { get; }
|
||||||
|
int CachedPrismaticCount { get; }
|
||||||
|
string CharTag { get; }
|
||||||
|
DateTime StatsStartTime { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -308,7 +308,9 @@
|
||||||
<Compile Include="CommandRouter.cs" />
|
<Compile Include="CommandRouter.cs" />
|
||||||
<Compile Include="Constants.cs" />
|
<Compile Include="Constants.cs" />
|
||||||
<Compile Include="GameEventRouter.cs" />
|
<Compile Include="GameEventRouter.cs" />
|
||||||
|
<Compile Include="IGameStats.cs" />
|
||||||
<Compile Include="IPluginLogger.cs" />
|
<Compile Include="IPluginLogger.cs" />
|
||||||
|
<Compile Include="QuestStreamingService.cs" />
|
||||||
<Compile Include="InventoryMonitor.cs" />
|
<Compile Include="InventoryMonitor.cs" />
|
||||||
<Compile Include="KillTracker.cs" />
|
<Compile Include="KillTracker.cs" />
|
||||||
<Compile Include="RareTracker.cs" />
|
<Compile Include="RareTracker.cs" />
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ using Mag.Shared.Constants;
|
||||||
namespace MosswartMassacre
|
namespace MosswartMassacre
|
||||||
{
|
{
|
||||||
[FriendlyName("Mosswart Massacre")]
|
[FriendlyName("Mosswart Massacre")]
|
||||||
public class PluginCore : PluginBase, IPluginLogger
|
public class PluginCore : PluginBase, IPluginLogger, IGameStats
|
||||||
{
|
{
|
||||||
// Hot Reload Support Properties
|
// Hot Reload Support Properties
|
||||||
private static string _assemblyDirectory = null;
|
private static string _assemblyDirectory = null;
|
||||||
|
|
@ -47,10 +47,9 @@ namespace MosswartMassacre
|
||||||
public static bool IsHotReload { get; set; }
|
public static bool IsHotReload { get; set; }
|
||||||
|
|
||||||
internal static PluginHost MyHost;
|
internal static PluginHost MyHost;
|
||||||
// Bridge properties for WebSocket telemetry until IGameStats migration (Phase 5)
|
// Static bridge properties for VVSTabbedMainView (reads from manager instances)
|
||||||
private static InventoryMonitor _staticInventoryMonitor;
|
private static InventoryMonitor _staticInventoryMonitor;
|
||||||
internal static int cachedPrismaticCount => _staticInventoryMonitor?.CachedPrismaticCount ?? 0;
|
internal static int cachedPrismaticCount => _staticInventoryMonitor?.CachedPrismaticCount ?? 0;
|
||||||
// Bridge properties for WebSocket telemetry until IGameStats migration (Phase 5)
|
|
||||||
private static KillTracker _staticKillTracker;
|
private static KillTracker _staticKillTracker;
|
||||||
internal static int totalKills => _staticKillTracker?.TotalKills ?? 0;
|
internal static int totalKills => _staticKillTracker?.TotalKills ?? 0;
|
||||||
internal static double killsPerHour => _staticKillTracker?.KillsPerHour ?? 0;
|
internal static double killsPerHour => _staticKillTracker?.KillsPerHour ?? 0;
|
||||||
|
|
@ -58,6 +57,16 @@ namespace MosswartMassacre
|
||||||
internal static int totalDeaths => _staticKillTracker?.TotalDeaths ?? 0;
|
internal static int totalDeaths => _staticKillTracker?.TotalDeaths ?? 0;
|
||||||
internal static DateTime statsStartTime => _staticKillTracker?.StatsStartTime ?? DateTime.Now;
|
internal static DateTime statsStartTime => _staticKillTracker?.StatsStartTime ?? DateTime.Now;
|
||||||
internal static DateTime lastKillTime => _staticKillTracker?.LastKillTime ?? DateTime.Now;
|
internal static DateTime lastKillTime => _staticKillTracker?.LastKillTime ?? DateTime.Now;
|
||||||
|
|
||||||
|
// IGameStats explicit implementation (for WebSocket telemetry)
|
||||||
|
int IGameStats.TotalKills => _staticKillTracker?.TotalKills ?? 0;
|
||||||
|
double IGameStats.KillsPerHour => _staticKillTracker?.KillsPerHour ?? 0;
|
||||||
|
int IGameStats.SessionDeaths => _staticKillTracker?.SessionDeaths ?? 0;
|
||||||
|
int IGameStats.TotalDeaths => _staticKillTracker?.TotalDeaths ?? 0;
|
||||||
|
int IGameStats.CachedPrismaticCount => _staticInventoryMonitor?.CachedPrismaticCount ?? 0;
|
||||||
|
string IGameStats.CharTag => CharTag;
|
||||||
|
DateTime IGameStats.StatsStartTime => _staticKillTracker?.StatsStartTime ?? DateTime.Now;
|
||||||
|
|
||||||
private static Timer vitalsTimer;
|
private static Timer vitalsTimer;
|
||||||
private static System.Windows.Forms.Timer commandTimer;
|
private static System.Windows.Forms.Timer commandTimer;
|
||||||
private static Timer characterStatsTimer;
|
private static Timer characterStatsTimer;
|
||||||
|
|
@ -122,7 +131,6 @@ namespace MosswartMassacre
|
||||||
|
|
||||||
// Quest Management for always-on quest streaming
|
// Quest Management for always-on quest streaming
|
||||||
public static QuestManager questManager;
|
public static QuestManager questManager;
|
||||||
private static Timer questStreamingTimer;
|
|
||||||
|
|
||||||
private static readonly Queue<string> _chatQueue = new Queue<string>();
|
private static readonly Queue<string> _chatQueue = new Queue<string>();
|
||||||
|
|
||||||
|
|
@ -132,6 +140,7 @@ namespace MosswartMassacre
|
||||||
private InventoryMonitor _inventoryMonitor;
|
private InventoryMonitor _inventoryMonitor;
|
||||||
private ChatEventRouter _chatEventRouter;
|
private ChatEventRouter _chatEventRouter;
|
||||||
private GameEventRouter _gameEventRouter;
|
private GameEventRouter _gameEventRouter;
|
||||||
|
private QuestStreamingService _questStreamingService;
|
||||||
private CommandRouter _commandRouter;
|
private CommandRouter _commandRouter;
|
||||||
|
|
||||||
protected override void Startup()
|
protected override void Startup()
|
||||||
|
|
@ -236,6 +245,7 @@ namespace MosswartMassacre
|
||||||
vTank.Enable();
|
vTank.Enable();
|
||||||
// Set logger for WebSocket
|
// Set logger for WebSocket
|
||||||
WebSocket.SetLogger(this);
|
WebSocket.SetLogger(this);
|
||||||
|
WebSocket.SetGameStats(this);
|
||||||
//lyssna på commands
|
//lyssna på commands
|
||||||
WebSocket.OnServerCommand += HandleServerCommand;
|
WebSocket.OnServerCommand += HandleServerCommand;
|
||||||
//starta inventory. Hanterar subscriptions i den med
|
//starta inventory. Hanterar subscriptions i den med
|
||||||
|
|
@ -305,14 +315,9 @@ namespace MosswartMassacre
|
||||||
commandTimer = null;
|
commandTimer = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stop and dispose quest streaming timer
|
// Stop quest streaming service
|
||||||
if (questStreamingTimer != null)
|
_questStreamingService?.Stop();
|
||||||
{
|
_questStreamingService = null;
|
||||||
questStreamingTimer.Stop();
|
|
||||||
questStreamingTimer.Elapsed -= OnQuestStreamingUpdate;
|
|
||||||
questStreamingTimer.Dispose();
|
|
||||||
questStreamingTimer = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stop and dispose character stats timer
|
// Stop and dispose character stats timer
|
||||||
if (characterStatsTimer != null)
|
if (characterStatsTimer != null)
|
||||||
|
|
@ -427,11 +432,9 @@ namespace MosswartMassacre
|
||||||
// Trigger full quest data refresh (same as clicking refresh button)
|
// Trigger full quest data refresh (same as clicking refresh button)
|
||||||
Views.FlagTrackerView.RefreshQuestData();
|
Views.FlagTrackerView.RefreshQuestData();
|
||||||
|
|
||||||
// Initialize quest streaming timer (30 seconds)
|
// Initialize quest streaming service (30 seconds)
|
||||||
questStreamingTimer = new Timer(Constants.QuestStreamingIntervalMs);
|
_questStreamingService = new QuestStreamingService(this);
|
||||||
questStreamingTimer.Elapsed += OnQuestStreamingUpdate;
|
_questStreamingService.Start();
|
||||||
questStreamingTimer.AutoReset = true;
|
|
||||||
questStreamingTimer.Start();
|
|
||||||
|
|
||||||
WriteToChat("[OK] Quest streaming initialized with full data refresh");
|
WriteToChat("[OK] Quest streaming initialized with full data refresh");
|
||||||
}
|
}
|
||||||
|
|
@ -470,102 +473,6 @@ namespace MosswartMassacre
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Quest Streaming Methods
|
|
||||||
private static void OnQuestStreamingUpdate(object sender, ElapsedEventArgs e)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// Debug: Log when timer fires
|
|
||||||
if (PluginSettings.Instance?.VerboseLogging == true)
|
|
||||||
{
|
|
||||||
WriteToChat("[QUEST-STREAM] Timer fired, checking conditions...");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stream high priority quest data via WebSocket
|
|
||||||
if (!WebSocketEnabled)
|
|
||||||
{
|
|
||||||
if (PluginSettings.Instance?.VerboseLogging == true)
|
|
||||||
{
|
|
||||||
WriteToChat("[QUEST-STREAM] WebSocket not enabled, skipping");
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (questManager?.QuestList == null || questManager.QuestList.Count == 0)
|
|
||||||
{
|
|
||||||
if (PluginSettings.Instance?.VerboseLogging == true)
|
|
||||||
{
|
|
||||||
WriteToChat($"[QUEST-STREAM] No quest data available (null: {questManager?.QuestList == null}, count: {questManager?.QuestList?.Count ?? 0})");
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var currentTime = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
|
|
||||||
|
|
||||||
// Find and stream priority quests (deduplicated by quest ID)
|
|
||||||
var priorityQuests = questManager.QuestList
|
|
||||||
.Where(q => IsHighPriorityQuest(q.Id))
|
|
||||||
.GroupBy(q => q.Id)
|
|
||||||
.Select(g => g.First()) // Take first occurrence of each quest ID
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
if (PluginSettings.Instance?.VerboseLogging == true)
|
|
||||||
{
|
|
||||||
WriteToChat($"[QUEST-STREAM] Found {priorityQuests.Count} priority quests to stream");
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var quest in priorityQuests)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
string questName = questManager.GetFriendlyQuestName(quest.Id);
|
|
||||||
long timeRemaining = quest.ExpireTime - currentTime;
|
|
||||||
string countdown = FormatCountdown(timeRemaining);
|
|
||||||
|
|
||||||
if (PluginSettings.Instance?.VerboseLogging == true)
|
|
||||||
{
|
|
||||||
WriteToChat($"[QUEST-STREAM] Sending: {questName} - {countdown}");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stream quest data
|
|
||||||
System.Threading.Tasks.Task.Run(() => WebSocket.SendQuestDataAsync(questName, countdown));
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
WriteToChat($"[QUEST-STREAM] Error streaming quest {quest.Id}: {ex.Message}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
WriteToChat($"[QUEST-STREAM] Error in timer handler: {ex.Message}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool IsHighPriorityQuest(string questId)
|
|
||||||
{
|
|
||||||
return questId == "stipendtimer_0812" || // Changed from stipendtimer_monthly to stipendtimer_0812
|
|
||||||
questId == "augmentationblankgemacquired" ||
|
|
||||||
questId == "insatiableeaterjaw";
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string FormatCountdown(long seconds)
|
|
||||||
{
|
|
||||||
if (seconds <= 0)
|
|
||||||
return "READY";
|
|
||||||
|
|
||||||
var timeSpan = TimeSpan.FromSeconds(seconds);
|
|
||||||
|
|
||||||
if (timeSpan.TotalDays >= 1)
|
|
||||||
return $"{(int)timeSpan.TotalDays}d {timeSpan.Hours:D2}h";
|
|
||||||
else if (timeSpan.TotalHours >= 1)
|
|
||||||
return $"{timeSpan.Hours}h {timeSpan.Minutes:D2}m";
|
|
||||||
else if (timeSpan.TotalMinutes >= 1)
|
|
||||||
return $"{timeSpan.Minutes}m {timeSpan.Seconds:D2}s";
|
|
||||||
else
|
|
||||||
return $"{timeSpan.Seconds}s";
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
private void InitializeForHotReload()
|
private void InitializeForHotReload()
|
||||||
{
|
{
|
||||||
|
|
@ -654,29 +561,18 @@ namespace MosswartMassacre
|
||||||
WriteToChat($"[ERROR] Quest manager hot reload failed: {ex.Message}");
|
WriteToChat($"[ERROR] Quest manager hot reload failed: {ex.Message}");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 9. Reinitialize quest streaming timer for hot reload
|
// 9. Reinitialize quest streaming service for hot reload
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Stop existing timer if any
|
_questStreamingService?.Stop();
|
||||||
if (questStreamingTimer != null)
|
_questStreamingService = new QuestStreamingService(this);
|
||||||
{
|
_questStreamingService.Start();
|
||||||
questStreamingTimer.Stop();
|
|
||||||
questStreamingTimer.Elapsed -= OnQuestStreamingUpdate;
|
|
||||||
questStreamingTimer.Dispose();
|
|
||||||
questStreamingTimer = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create new timer
|
|
||||||
questStreamingTimer = new Timer(Constants.QuestStreamingIntervalMs);
|
|
||||||
questStreamingTimer.Elapsed += OnQuestStreamingUpdate;
|
|
||||||
questStreamingTimer.AutoReset = true;
|
|
||||||
questStreamingTimer.Start();
|
|
||||||
|
|
||||||
WriteToChat("[OK] Quest streaming timer reinitialized (30s interval)");
|
WriteToChat("[OK] Quest streaming service reinitialized (30s interval)");
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
WriteToChat($"[ERROR] Quest streaming timer hot reload failed: {ex.Message}");
|
WriteToChat($"[ERROR] Quest streaming service hot reload failed: {ex.Message}");
|
||||||
}
|
}
|
||||||
|
|
||||||
WriteToChat("Hot reload initialization completed!");
|
WriteToChat("Hot reload initialization completed!");
|
||||||
|
|
@ -1485,7 +1381,7 @@ namespace MosswartMassacre
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
WriteToChat("=== Quest Streaming Status ===");
|
WriteToChat("=== Quest Streaming Status ===");
|
||||||
WriteToChat($"Timer Active: {questStreamingTimer != null && questStreamingTimer.Enabled}");
|
WriteToChat($"Timer Active: {_questStreamingService?.IsRunning ?? false}");
|
||||||
WriteToChat($"WebSocket Enabled: {WebSocketEnabled}");
|
WriteToChat($"WebSocket Enabled: {WebSocketEnabled}");
|
||||||
WriteToChat($"Quest Manager: {(questManager != null ? "Active" : "Not Active")}");
|
WriteToChat($"Quest Manager: {(questManager != null ? "Active" : "Not Active")}");
|
||||||
WriteToChat($"Quest Count: {questManager?.QuestList?.Count ?? 0}");
|
WriteToChat($"Quest Count: {questManager?.QuestList?.Count ?? 0}");
|
||||||
|
|
@ -1493,7 +1389,7 @@ namespace MosswartMassacre
|
||||||
if (questManager?.QuestList != null)
|
if (questManager?.QuestList != null)
|
||||||
{
|
{
|
||||||
var priorityQuests = questManager.QuestList
|
var priorityQuests = questManager.QuestList
|
||||||
.Where(q => IsHighPriorityQuest(q.Id))
|
.Where(q => QuestStreamingService.IsHighPriorityQuest(q.Id))
|
||||||
.GroupBy(q => q.Id)
|
.GroupBy(q => q.Id)
|
||||||
.Select(g => g.First())
|
.Select(g => g.First())
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
|
||||||
133
MosswartMassacre/QuestStreamingService.cs
Normal file
133
MosswartMassacre/QuestStreamingService.cs
Normal file
|
|
@ -0,0 +1,133 @@
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Timers;
|
||||||
|
|
||||||
|
namespace MosswartMassacre
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Streams high-priority quest timer data via WebSocket on a 30-second interval.
|
||||||
|
/// </summary>
|
||||||
|
internal class QuestStreamingService
|
||||||
|
{
|
||||||
|
private readonly IPluginLogger _logger;
|
||||||
|
private Timer _timer;
|
||||||
|
|
||||||
|
internal QuestStreamingService(IPluginLogger logger)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void Start()
|
||||||
|
{
|
||||||
|
_timer = new Timer(Constants.QuestStreamingIntervalMs);
|
||||||
|
_timer.Elapsed += OnTimerElapsed;
|
||||||
|
_timer.AutoReset = true;
|
||||||
|
_timer.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void Stop()
|
||||||
|
{
|
||||||
|
if (_timer != null)
|
||||||
|
{
|
||||||
|
_timer.Stop();
|
||||||
|
_timer.Elapsed -= OnTimerElapsed;
|
||||||
|
_timer.Dispose();
|
||||||
|
_timer = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal bool IsRunning => _timer != null && _timer.Enabled;
|
||||||
|
|
||||||
|
private void OnTimerElapsed(object sender, ElapsedEventArgs e)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (PluginSettings.Instance?.VerboseLogging == true)
|
||||||
|
{
|
||||||
|
_logger?.Log("[QUEST-STREAM] Timer fired, checking conditions...");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!PluginCore.WebSocketEnabled)
|
||||||
|
{
|
||||||
|
if (PluginSettings.Instance?.VerboseLogging == true)
|
||||||
|
{
|
||||||
|
_logger?.Log("[QUEST-STREAM] WebSocket not enabled, skipping");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var questManager = PluginCore.questManager;
|
||||||
|
if (questManager?.QuestList == null || questManager.QuestList.Count == 0)
|
||||||
|
{
|
||||||
|
if (PluginSettings.Instance?.VerboseLogging == true)
|
||||||
|
{
|
||||||
|
_logger?.Log($"[QUEST-STREAM] No quest data available (null: {questManager?.QuestList == null}, count: {questManager?.QuestList?.Count ?? 0})");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var currentTime = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
|
||||||
|
|
||||||
|
var priorityQuests = questManager.QuestList
|
||||||
|
.Where(q => IsHighPriorityQuest(q.Id))
|
||||||
|
.GroupBy(q => q.Id)
|
||||||
|
.Select(g => g.First())
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
if (PluginSettings.Instance?.VerboseLogging == true)
|
||||||
|
{
|
||||||
|
_logger?.Log($"[QUEST-STREAM] Found {priorityQuests.Count} priority quests to stream");
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var quest in priorityQuests)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string questName = questManager.GetFriendlyQuestName(quest.Id);
|
||||||
|
long timeRemaining = quest.ExpireTime - currentTime;
|
||||||
|
string countdown = FormatCountdown(timeRemaining);
|
||||||
|
|
||||||
|
if (PluginSettings.Instance?.VerboseLogging == true)
|
||||||
|
{
|
||||||
|
_logger?.Log($"[QUEST-STREAM] Sending: {questName} - {countdown}");
|
||||||
|
}
|
||||||
|
|
||||||
|
System.Threading.Tasks.Task.Run(() => WebSocket.SendQuestDataAsync(questName, countdown));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger?.Log($"[QUEST-STREAM] Error streaming quest {quest.Id}: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger?.Log($"[QUEST-STREAM] Error in timer handler: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static bool IsHighPriorityQuest(string questId)
|
||||||
|
{
|
||||||
|
return questId == "stipendtimer_0812" ||
|
||||||
|
questId == "augmentationblankgemacquired" ||
|
||||||
|
questId == "insatiableeaterjaw";
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static string FormatCountdown(long seconds)
|
||||||
|
{
|
||||||
|
if (seconds <= 0)
|
||||||
|
return "READY";
|
||||||
|
|
||||||
|
var timeSpan = TimeSpan.FromSeconds(seconds);
|
||||||
|
|
||||||
|
if (timeSpan.TotalDays >= 1)
|
||||||
|
return $"{(int)timeSpan.TotalDays}d {timeSpan.Hours:D2}h";
|
||||||
|
else if (timeSpan.TotalHours >= 1)
|
||||||
|
return $"{timeSpan.Hours}h {timeSpan.Minutes:D2}m";
|
||||||
|
else if (timeSpan.TotalMinutes >= 1)
|
||||||
|
return $"{timeSpan.Minutes}m {timeSpan.Seconds:D2}s";
|
||||||
|
else
|
||||||
|
return $"{timeSpan.Seconds}s";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -36,6 +36,7 @@ namespace MosswartMassacre
|
||||||
private const int IntervalSec = 5;
|
private const int IntervalSec = 5;
|
||||||
private static string SessionId = "";
|
private static string SessionId = "";
|
||||||
private static IPluginLogger _logger;
|
private static IPluginLogger _logger;
|
||||||
|
private static IGameStats _gameStats;
|
||||||
|
|
||||||
// ─── cached prismatic taper count ─── (now handled by PluginCore event system)
|
// ─── cached prismatic taper count ─── (now handled by PluginCore event system)
|
||||||
|
|
||||||
|
|
@ -53,6 +54,7 @@ namespace MosswartMassacre
|
||||||
// ─── public API ─────────────────────────────
|
// ─── public API ─────────────────────────────
|
||||||
|
|
||||||
public static void SetLogger(IPluginLogger logger) => _logger = logger;
|
public static void SetLogger(IPluginLogger logger) => _logger = logger;
|
||||||
|
public static void SetGameStats(IGameStats gameStats) => _gameStats = gameStats;
|
||||||
|
|
||||||
public static void Start()
|
public static void Start()
|
||||||
{
|
{
|
||||||
|
|
@ -350,33 +352,31 @@ namespace MosswartMassacre
|
||||||
|
|
||||||
// ─── payload builder ──────────────────────────────
|
// ─── payload builder ──────────────────────────────
|
||||||
|
|
||||||
// Removed old cache system - now using PluginCore.cachedPrismaticCount
|
|
||||||
|
|
||||||
private static string BuildPayloadJson()
|
private static string BuildPayloadJson()
|
||||||
{
|
{
|
||||||
var tele = new ClientTelemetry();
|
var tele = new ClientTelemetry();
|
||||||
var coords = Coordinates.Me;
|
var coords = Coordinates.Me;
|
||||||
|
var stats = _gameStats;
|
||||||
var payload = new
|
var payload = new
|
||||||
{
|
{
|
||||||
type = "telemetry",
|
type = "telemetry",
|
||||||
character_name = CoreManager.Current.CharacterFilter.Name,
|
character_name = CoreManager.Current.CharacterFilter.Name,
|
||||||
char_tag = PluginCore.CharTag,
|
char_tag = stats?.CharTag ?? "",
|
||||||
session_id = SessionInfo.GuidString,
|
session_id = SessionInfo.GuidString,
|
||||||
timestamp = DateTime.UtcNow.ToString("o"),
|
timestamp = DateTime.UtcNow.ToString("o"),
|
||||||
ew = coords.EW,
|
ew = coords.EW,
|
||||||
ns = coords.NS,
|
ns = coords.NS,
|
||||||
z = coords.Z,
|
z = coords.Z,
|
||||||
kills = PluginCore.totalKills,
|
kills = stats?.TotalKills ?? 0,
|
||||||
kills_per_hour = PluginCore.killsPerHour.ToString("F0"),
|
kills_per_hour = (stats?.KillsPerHour ?? 0).ToString("F0"),
|
||||||
onlinetime = (DateTime.Now - PluginCore.statsStartTime).ToString(@"dd\.hh\:mm\:ss"),
|
onlinetime = (DateTime.Now - (stats?.StatsStartTime ?? DateTime.Now)).ToString(@"dd\.hh\:mm\:ss"),
|
||||||
deaths = PluginCore.sessionDeaths.ToString(),
|
deaths = (stats?.SessionDeaths ?? 0).ToString(),
|
||||||
total_deaths = PluginCore.totalDeaths.ToString(),
|
total_deaths = (stats?.TotalDeaths ?? 0).ToString(),
|
||||||
prismatic_taper_count = PluginCore.cachedPrismaticCount.ToString(),
|
prismatic_taper_count = (stats?.CachedPrismaticCount ?? 0).ToString(),
|
||||||
vt_state = VtankControl.VtGetMetaState(),
|
vt_state = VtankControl.VtGetMetaState(),
|
||||||
mem_mb = tele.MemoryBytes,
|
mem_mb = tele.MemoryBytes,
|
||||||
cpu_pct = tele.GetCpuUsage(),
|
cpu_pct = tele.GetCpuUsage(),
|
||||||
mem_handles = tele.HandleCount
|
mem_handles = tele.HandleCount
|
||||||
|
|
||||||
};
|
};
|
||||||
return JsonConvert.SerializeObject(payload);
|
return JsonConvert.SerializeObject(payload);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue