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 activeTimeTracker = new Dictionary(); 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("StatTracker"); activeTimeTracker = new Dictionary(); } #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 timePlayed = new Dictionary(); public Dictionary entityPlaced = new Dictionary(); public Dictionary playerDeath = new Dictionary(); public int totalDeaths; public int rocketCount; public int explosiveCount; } void Loaded() { storedData = Interface.Oxide.DataFileSystem.ReadObject("StatTracker"); if (storedData == null) { storedData = new StoredData(); } } void SaveData() { Interface.Oxide.DataFileSystem.WriteObject("StatTracker", storedData); } #endregion }