C#:
using Oxide.Core;
using Oxide.Core.Libraries.Covalence;
using Oxide.Core.Plugins;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace Oxide.Plugins;
[Info("StatTracker", "Fateeh", "0.0.2")]
[Description("StatTracker for track your players in server")]
class StatTracker : RustPlugin
{
#region Fields
static StatTracker instance;
public Dictionary<string, DateTime> activeTimeTracker = new Dictionary<string, DateTime>();
private string ADMINPERMISSION = "stattracker.admin";
private string PERMISSION = "stattracker.use";
#endregion
#region Init
void OnServerInitialized()
{
permission.RegisterPermission(ADMINPERMISSION, this);
permission.RegisterPermission(PERMISSION, this);
storedData = Interface.Oxide.DataFileSystem.ReadObject<StoredData>("StatTracker");
activeTimeTracker = new Dictionary<string, DateTime>();
}
#endregion
#region Hooks
void OnPlayerConnected(BasePlayer player)
{
activeTimeTracker[player.UserIDString] = DateTime.Now;
}
void OnPlayerDisconnected(BasePlayer player, string reason)
{
string userId = player.UserIDString;
if (activeTimeTracker != null && activeTimeTracker.ContainsKey(userId))
{
UpdatePlayerTime(userId);
activeTimeTracker.Remove(userId);
}
}
void OnRocketLaunched(BasePlayer player, BaseEntity entity)
{
storedData.rocketCount++;
SaveData();
}
void OnExplosiveThrown(BasePlayer player, BaseEntity entity, ThrownWeapon item)
{
storedData.explosiveCount++;
SaveData();
}
object OnConstructionPlace(BaseEntity entity, Construction component, Construction.Target constructionTarget, BasePlayer player)
{
if (storedData.entityPlaced.ContainsKey(player.UserIDString))
{
storedData.entityPlaced[player.UserIDString]++;
}
else
{
storedData.entityPlaced[player.UserIDString] = 1;
}
SaveData();
return null;
}
object OnPlayerDeath(BasePlayer player, HitInfo info)
{
if (player)
{
if (storedData.playerDeath.ContainsKey(player.UserIDString))
{
storedData.playerDeath[player.UserIDString]++;
}
else
{
storedData.playerDeath[player.UserIDString] = 1;
}
storedData.totalDeaths++;
SaveData();
}
return null;
}
#endregion
#region Function
void ShowPlayerStats(BasePlayer sourcePlayer, BasePlayer targetPlayer)
{
TimeSpan totalTime = TimeSpan.Zero;
int entityCount = 0;
int deathCount = 0;
foreach (var item in storedData.timePlayed)
{
if (item.Key == targetPlayer.UserIDString)
{
totalTime = item.Value;
}
}
foreach (var item in storedData.entityPlaced)
{
if (item.Key == targetPlayer.UserIDString)
{
entityCount = item.Value;
}
}
foreach (var item in storedData.playerDeath)
{
if (item.Key == targetPlayer.UserIDString)
{
entityCount = item.Value;
}
}
UpdatePlayerTime(targetPlayer.UserIDString);
SendReply(sourcePlayer, $"{targetPlayer.displayName} played for {totalTime.Hours} hours and {totalTime.Minutes} minutes. They also built {entityCount.ToString()} structures and had {deathCount.ToString()} deaths.");
}
BasePlayer FindPlayerByName(string playerName)
{
foreach (BasePlayer player in BasePlayer.activePlayerList)
{
string displayNameLower = player.displayName.ToLower();
playerName = playerName.ToLower();
if (displayNameLower.Contains(playerName) || playerName.Contains(displayNameLower))
{
return player;
}
}
return null;
}
void UpdatePlayerTime(string userId)
{
if (activeTimeTracker.ContainsKey(userId))
{
DateTime startTime = activeTimeTracker[userId];
DateTime endTime = DateTime.Now;
TimeSpan totalTime = endTime - startTime;
if (storedData.timePlayed.ContainsKey(userId))
{
storedData.timePlayed[userId] += totalTime;
}
else
{
storedData.timePlayed[userId] = totalTime;
}
SaveData();
}
}
#endregion
#region Commands
[ChatCommand("showplayerstats")]
void ShowSpecificPlayerStats(BasePlayer player, string command, string[] args)
{
if (!permission.UserHasPermission(player.UserIDString, ADMINPERMISSION))
{
SendReply(player, "You do not have permission to use this command.");
return;
}
if (args.Length == 0)
{
SendReply(player, "Syntax: /showplayerstats \"name\"");
return;
}
string targetPlayerName = args[0];
BasePlayer targetPlayer = FindPlayerByName(targetPlayerName);
if (targetPlayer == null)
{
SendReply(player, $"Player '{targetPlayerName}' not found.");
return;
}
ShowPlayerStats(player, targetPlayer);
}
[ChatCommand("showserverstats")]
void ShowServerStats(BasePlayer player)
{
if (!permission.UserHasPermission(player.UserIDString, ADMINPERMISSION))
{
SendReply(player, "You do not have permission to use this command.");
return;
}
TimeSpan allPlayersTime = TimeSpan.Zero;
foreach (var time in storedData.timePlayed)
{
allPlayersTime += time.Value;
}
SendReply(player, $"Total game time: {allPlayersTime.Hours} hours. During this period, {storedData.rocketCount.ToString()} rockets were fired, " +
$"{storedData.explosiveCount.ToString()} explosives were thrown, and there were {storedData.totalDeaths.ToString()} deaths.");
}
[ChatCommand("showmystats")]
void ShowPlayerStats(BasePlayer player)
{
if (!permission.UserHasPermission(player.UserIDString, PERMISSION))
{
SendReply(player, "You do not have permission to use this command.");
return;
}
TimeSpan totalTime = new();
int entityCount = 0;
int deathCount = 0;
foreach (var item in storedData.timePlayed)
{
if (item.Key == player.UserIDString)
{
totalTime = item.Value;
}
}
foreach (var item in storedData.entityPlaced)
{
if (item.Key == player.UserIDString)
{
entityCount = item.Value;
}
}
foreach (var item in storedData.playerDeath)
{
if (item.Key == player.UserIDString)
{
deathCount = item.Value;
}
}
UpdatePlayerTime(player.UserIDString);
SendReply(player, $"{player.displayName}, you have played for {totalTime.Hours} hours and {totalTime.Minutes} minutes. Additionally, you have placed {entityCount.ToString()} constructions and experienced {deathCount.ToString()} deaths.");
}
#endregion
#region Data
StoredData storedData;
class StoredData
{
public Dictionary<string, TimeSpan> timePlayed = new Dictionary<string, TimeSpan>();
public Dictionary<string, int> entityPlaced = new Dictionary<string, int>();
public Dictionary<string, int> playerDeath = new Dictionary<string, int>();
public int totalDeaths;
public int rocketCount;
public int explosiveCount;
}
void Loaded()
{
storedData = Interface.Oxide.DataFileSystem.ReadObject<StoredData>("StatTracker");
if (storedData == null)
{
storedData = new StoredData();
}
}
void SaveData()
{
Interface.Oxide.DataFileSystem.WriteObject("StatTracker", storedData);
}
#endregion
}