Compare commits

...

2 commits

Author SHA1 Message Date
Heavy Bob
ad773f6790 Added Initialization Waits
This will help prevent reading the old game.log on boot.
2025-04-12 10:29:56 +10:00
Heavy Bob
e88876a620 Hash Kills
This change updates the .csv to store kill hashes and also stores hashes made in memory. This should prevent reporting the same kill twice or saving it to the .csv twice. This will break the old .csv however it is renamed to .old with the previous change.
2025-04-12 07:43:28 +10:00
5 changed files with 153 additions and 30 deletions

View file

@ -25,6 +25,9 @@ public partial class HomePage : UserControl
private bool _isLogHandlerRunning = false;
private int _counter = 1;
private System.Timers.Timer _counterTimer;
private bool _isInitializing = false;
private System.Timers.Timer? _initializationTimer;
private bool _wasStarCitizenRunningOnStart = false;
public HomePage()
{
@ -42,6 +45,18 @@ public partial class HomePage : UserControl
AdjustFontSize(KillTallyTextBox);
AddKillHistoryKillsToUI();
// Check if Star Citizen is already running
_wasStarCitizenRunningOnStart = IsStarCitizenRunning();
if (_wasStarCitizenRunningOnStart)
{
UpdateStatusIndicator(true);
InitializeLogHandler();
}
else
{
UpdateStatusIndicator(false);
}
// Initialize and start the status check timer
_statusCheckTimer = new System.Timers.Timer(1000); // Check every second
_statusCheckTimer.Elapsed += CheckStarCitizenStatus;
@ -51,16 +66,6 @@ public partial class HomePage : UserControl
_counterTimer = new System.Timers.Timer(1000); // Update every second
_counterTimer.Elapsed += UpdateCounter;
_counterTimer.Start();
// Check if Star Citizen is already running and initialize accordingly
if (IsStarCitizenRunning())
{
Dispatcher.Invoke(() =>
{
UpdateStatusIndicator(true);
InitializeLogHandler(); // Then initialize the log handler
});
}
}
private void CheckStarCitizenStatus(object? sender, ElapsedEventArgs e)
@ -68,14 +73,44 @@ public partial class HomePage : UserControl
bool isRunning = IsStarCitizenRunning();
Dispatcher.Invoke(() =>
{
UpdateStatusIndicator(isRunning);
if (_isInitializing)
{
return; // Don't update status while initializing
}
if (isRunning)
{
if (!_isLogHandlerRunning)
{
// Game is running, start log monitoring and read initial states
InitializeLogHandler();
if (_wasStarCitizenRunningOnStart)
{
// Game was already running on start, initialize immediately
UpdateStatusIndicator(true);
InitializeLogHandler();
}
else
{
// Game started after app launch, use initialization delay
_isInitializing = true;
UpdateStatusIndicator(false, true); // Set to yellow for initialization
_initializationTimer = new System.Timers.Timer(20000); // 20 seconds
_initializationTimer.Elapsed += (sender, e) =>
{
_isInitializing = false;
_initializationTimer?.Stop();
_initializationTimer?.Dispose();
_initializationTimer = null;
Dispatcher.Invoke(() =>
{
// Game is running, start log monitoring and read initial states
UpdateStatusIndicator(true);
InitializeLogHandler();
});
};
_initializationTimer.Start();
}
}
}
else
@ -96,16 +131,23 @@ public partial class HomePage : UserControl
_logHandler?.StopMonitoring();
_isLogHandlerRunning = false;
}
UpdateStatusIndicator(false);
}
});
}
private void UpdateStatusIndicator(bool isRunning)
private void UpdateStatusIndicator(bool isRunning, bool isInitializing = false)
{
if (isRunning)
if (isInitializing)
{
StatusLight.Fill = new SolidColorBrush(Colors.Yellow);
StatusText.Text = "TrackR\nInitializing";
}
else if (isRunning)
{
StatusLight.Fill = new SolidColorBrush(Colors.Green);
StatusText.Text = "TrackR\nActive";
StatusText.Text = "TrackR\nRunning";
}
else
{
@ -192,7 +234,8 @@ public partial class HomePage : UserControl
TrackRver = "2.10",
Enlisted = playerData?.JoinDate,
KillTime = ((DateTimeOffset)DateTime.ParseExact(actorDeathData.Timestamp, "yyyy-MM-ddTHH:mm:ss.fffZ", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal)).ToUnixTimeSeconds().ToString(),
PFP = playerData?.PFPURL ?? "https://cdn.robertsspaceindustries.com/static/images/account/avatar_default_big.jpg"
PFP = playerData?.PFPURL ?? "https://cdn.robertsspaceindustries.com/static/images/account/avatar_default_big.jpg",
Hash = WebHandler.GenerateKillHash(actorDeathData.VictimPilot, ((DateTimeOffset)DateTime.ParseExact(actorDeathData.Timestamp, "yyyy-MM-ddTHH:mm:ss.fffZ", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal)).ToUnixTimeSeconds())
};
switch (LocalPlayerData.CurrentGameMode)
@ -205,6 +248,13 @@ public partial class HomePage : UserControl
break;
}
// Check if this is a duplicate kill
if (WebHandler.IsDuplicateKill(killData.Hash))
{
Console.WriteLine("Duplicate kill detected, skipping...");
return;
}
// Add kill to UI
Dispatcher.Invoke(() =>
{

View file

@ -7,8 +7,8 @@ namespace AutoTrackR2;
public class KillHistoryManager
{
private string _killHistoryPath;
private readonly string _headers = "KillTime,EnemyPilot,EnemyShip,Enlisted,RecordNumber,OrgAffiliation,Player,Weapon,Ship,Method,Mode,GameVersion,TrackRver,Logged,PFP\n";
private readonly string _headers = "KillTime,EnemyPilot,EnemyShip,Enlisted,RecordNumber,OrgAffiliation,Player,Weapon,Ship,Method,Mode,GameVersion,TrackRver,Logged,PFP,Hash\n";
public KillHistoryManager(string logPath)
{
_killHistoryPath = logPath;
@ -89,8 +89,8 @@ public class KillHistoryManager
// Append the new kill data to the CSV file
var csv = new StringBuilder();
csv.AppendLine($"\"{killData.KillTime}\",\"{killData.EnemyPilot}\",\"{killData.EnemyShip}\",\"{killData.Enlisted}\",\"{killData.RecordNumber}\",\"{killData.OrgAffiliation}\",\"{killData.Player}\",\"{killData.Weapon}\",\"{killData.Ship}\",\"{killData.Method}\",\"{killData.Mode}\",\"{killData.GameVersion}\",\"{killData.TrackRver}\",\"{killData.Logged}\",\"{killData.PFP}\"");
csv.AppendLine($"\"{killData.KillTime}\",\"{killData.EnemyPilot}\",\"{killData.EnemyShip}\",\"{killData.Enlisted}\",\"{killData.RecordNumber}\",\"{killData.OrgAffiliation}\",\"{killData.Player}\",\"{killData.Weapon}\",\"{killData.Ship}\",\"{killData.Method}\",\"{killData.Mode}\",\"{killData.GameVersion}\",\"{killData.TrackRver}\",\"{killData.Logged}\",\"{killData.PFP}\",\"{killData.Hash}\"");
// Check file can be written to
try
{
@ -138,7 +138,8 @@ public class KillHistoryManager
GameVersion = data?[11],
TrackRver = data?[12],
Logged = data?[13],
PFP = data?[14]
PFP = data?[14],
Hash = data?[15]
});
}

View file

@ -30,8 +30,11 @@ public class LogHandler
private CancellationTokenSource? _cancellationTokenSource;
private GameProcessState _gameProcessState = GameProcessState.NotRunning;
private bool _isMonitoring = false;
private bool _isInitializing = false;
private System.Timers.Timer? _initializationTimer;
public bool IsMonitoring => _isMonitoring;
public bool IsInitializing => _isInitializing;
// Handlers that should be run on every log entry
// Overlap with _startupEventHandlers is fine
@ -62,6 +65,37 @@ public class LogHandler
throw new FileNotFoundException("Log file not found", _logPath);
}
// Check if Star Citizen is running
if (!IsStarCitizenRunning())
{
StartInitializationDelay();
return;
}
InitializeLogHandler();
}
private void StartInitializationDelay()
{
_isInitializing = true;
_initializationTimer = new System.Timers.Timer(20000); // 20 seconds
_initializationTimer.Elapsed += (sender, e) =>
{
_isInitializing = false;
_initializationTimer?.Stop();
_initializationTimer?.Dispose();
_initializationTimer = null;
if (IsStarCitizenRunning())
{
InitializeLogHandler();
}
};
_initializationTimer.Start();
}
private void InitializeLogHandler()
{
_fileStream = new FileStream(_logPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
_reader = new StreamReader(_fileStream);
@ -75,6 +109,11 @@ public class LogHandler
StartMonitoring();
}
private bool IsStarCitizenRunning()
{
return Process.GetProcessesByName("StarCitizen").Length > 0;
}
public void StartMonitoring()
{
if (_isMonitoring) return;
@ -156,14 +195,26 @@ public class LogHandler
GameProcessState newGameProcessState = process != null ? GameProcessState.Running : GameProcessState.NotRunning;
if (newGameProcessState == GameProcessState.Running && _gameProcessState == GameProcessState.NotRunning)
{
// Game process went from NotRunning to Running, so reload the Game.log file
Console.WriteLine("Game process started, reloading log file");
// Game process went from NotRunning to Running, wait 20 seconds before reloading
Console.WriteLine("Game process started, waiting 20 seconds before initializing...");
_isInitializing = true;
_reader?.Close();
_fileStream?.Close();
_initializationTimer = new System.Timers.Timer(20000); // 20 seconds
_initializationTimer.Elapsed += (sender, e) =>
{
_isInitializing = false;
_initializationTimer?.Stop();
_initializationTimer?.Dispose();
_initializationTimer = null;
_fileStream = new FileStream(_logPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
_reader = new StreamReader(_fileStream);
Console.WriteLine("Initialization delay complete, reloading log file");
_reader?.Close();
_fileStream?.Close();
_fileStream = new FileStream(_logPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
_reader = new StreamReader(_fileStream);
};
_initializationTimer.Start();
}
_gameProcessState = newGameProcessState;
}

View file

@ -29,4 +29,5 @@ public struct KillData
public string? TrackRver;
public string? Logged;
public string? PFP;
public string? Hash;
}

View file

@ -6,11 +6,19 @@ using System.Text.RegularExpressions;
using AutoTrackR2.LogEventHandlers;
using System.Globalization;
using System.Security.Cryptography;
using System.Collections.Generic;
namespace AutoTrackR2;
public static class WebHandler
{
private static HashSet<string> _recordedKillHashes = new HashSet<string>();
public static bool IsDuplicateKill(string hash)
{
return _recordedKillHashes.Contains(hash);
}
class APIKillData
{
public string? victim_ship { get; set; }
@ -28,7 +36,7 @@ public static class WebHandler
public string hash { get; set; } = string.Empty;
}
private static string GenerateKillHash(string victimName, long timestamp)
public static string GenerateKillHash(string victimName, long timestamp)
{
// Combine victim name and timestamp
string combined = $"{victimName}_{timestamp}";
@ -105,6 +113,15 @@ public static class WebHandler
public static async Task SubmitKill(KillData killData)
{
var timestamp = long.Parse(killData.KillTime!);
var hash = GenerateKillHash(killData.EnemyPilot!, timestamp);
// Check if this kill has already been recorded
if (_recordedKillHashes.Contains(hash))
{
Console.WriteLine("Duplicate kill detected, skipping...");
return;
}
var apiKillData = new APIKillData
{
victim_ship = killData.EnemyShip,
@ -119,7 +136,7 @@ public static class WebHandler
trackr_version = killData.TrackRver,
location = killData.Location,
time = timestamp,
hash = GenerateKillHash(killData.EnemyPilot!, timestamp)
hash = hash
};
if (string.IsNullOrEmpty(apiKillData.rsi))
@ -175,6 +192,9 @@ public static class WebHandler
var responseContent = await response.Content.ReadAsStringAsync();
Console.WriteLine($"Response: {responseContent}");
// Add the hash to our recorded hashes
_recordedKillHashes.Add(hash);
// Only process streamer data if streamlink is enabled
if (ConfigManager.StreamlinkEnabled == 1)
{