C#:
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Oxide.Core;
using Oxide.Core.Plugins;
using Newtonsoft.Json;
// ____ _ _ _
// / ___|(_) __ _(_) | ___
// \___ \| |/ _` | | |/ _ \
// ___) | | (_| | | | (_) |
// |____/|_|\__, |_|_|\___/
// |___/
// ☽✧✵✧✵✧✵✧✵✧✵✧✵✧☾
// ✦ RUST PLUGINS ✦
// ✦ Sigilo.dev ✦
// ☽✧✵✧✵✧✵✧✵✧✵✧✵✧☾
namespace Oxide.Plugins
{
[Info("KDR", "Sigilo", "1.0.1")]
[Description("Shows kills, deaths, KDR and a top 10 leaderboard")]
class KDR : RustPlugin
{
private const string PERMISSION_NAME = "kdr.use";
private ConcurrentDictionary<string, (int Kills, int Deaths)> playerStats = new ConcurrentDictionary<string, (int, int)>();
private ConcurrentDictionary<string, PlayerKDR> playerKDR = new ConcurrentDictionary<string, PlayerKDR>();
class PlayerKDR
{
public string UserID { get; set; }
public string Name { get; set; }
public float KDR { get; set; }
}
void Init()
{
permission.RegisterPermission(PERMISSION_NAME, this);
cmd.AddChatCommand("kdr", this, "CmdKDR");
cmd.AddChatCommand("kdrtop", this, "CmdKDRTop");
}
void Loaded()
{
var data = Interface.Oxide.DataFileSystem.ReadObject<Dictionary<string, (int, int)>>("KDRData");
foreach (var entry in data)
{
playerStats[entry.Key] = entry.Value;
}
try
{
playerKDR = new ConcurrentDictionary<string, PlayerKDR>(Interface.Oxide.DataFileSystem.ReadObject<Dictionary<string, PlayerKDR>>("KDR").ToDictionary(entry => entry.Key, entry => entry.Value));
}
catch (JsonReaderException)
{
Puts("Error reading KDR data. The data might be in an incorrect format.");
playerKDR = new ConcurrentDictionary<string, PlayerKDR>();
}
}
void Unload()
{
Interface.Oxide.DataFileSystem.WriteObject("KDRData", playerStats.ToDictionary(entry => entry.Key, entry => entry.Value));
Interface.Oxide.DataFileSystem.WriteObject("KDR", playerKDR.ToDictionary(entry => entry.Key, entry => entry.Value));
}
void OnPlayerDeath(BasePlayer player, HitInfo info)
{
if (info?.InitiatorPlayer != null && player != null && player.userID != 0)
{
if (info.InitiatorPlayer.userID != player.userID)
{
OnPlayerKill(info.InitiatorPlayer, player);
}
}
}
void OnPlayerKill(BasePlayer killer, BasePlayer victim)
{
string killerId = killer.UserIDString;
string victimId = victim.UserIDString;
if (!IsValidSteamID(victim.userID))
{
return;
}
playerStats.AddOrUpdate(killerId, (1, 0), (key, oldValue) => (oldValue.Kills + 1, oldValue.Deaths));
playerStats.AddOrUpdate(victimId, (0, 1), (key, oldValue) => (oldValue.Kills, oldValue.Deaths + 1));
Task.Run(() => UpdateKDR(killerId, victimId));
}
async Task UpdateKDR(string killerId, string victimId)
{
float killerKDR = CalculateKDR(killerId);
float victimKDR = CalculateKDR(victimId);
playerKDR[killerId] = new PlayerKDR { UserID = killerId, Name = covalence.Players.FindPlayerById(killerId)?.Name ?? "Unknown", KDR = killerKDR };
playerKDR[victimId] = new PlayerKDR { UserID = victimId, Name = covalence.Players.FindPlayerById(victimId)?.Name ?? "Unknown", KDR = victimKDR };
}
float CalculateKDR(string playerId)
{
var stats = playerStats.GetOrAdd(playerId, (0, 0));
return stats.Deaths != 0 ? (float)stats.Kills / stats.Deaths : stats.Kills;
}
[ChatCommand("kdr")]
void CmdKDR(BasePlayer player, string command, string[] args)
{
string playerId = player.UserIDString;
if (!permission.UserHasPermission(playerId, PERMISSION_NAME))
{
SendReply(player, "You do not have permission to use this command.");
return;
}
var stats = playerStats.GetOrAdd(playerId, (0, 0));
float kdr = playerKDR.ContainsKey(playerId) ? playerKDR[playerId].KDR : CalculateKDR(playerId);
SendReply(player, $"Your kills: <color=#ff686b>{stats.Kills}</color>, deaths: <color=#ff686b>{stats.Deaths}</color>, KDR: <color=#ff686b>{kdr.ToString("0.0")}</color>.");
}
[ChatCommand("kdrtop")]
void CmdKDRTop(BasePlayer player, string command, string[] args)
{
string playerId = player.UserIDString;
if (!permission.UserHasPermission(playerId, PERMISSION_NAME))
{
SendReply(player, "You do not have permission to use this command.");
return;
}
var topKDRs = playerKDR.Values.OrderByDescending(x => x.KDR).Take(10);
string message = "<color=#ff686b>Top KDRs:</color>\n";
foreach (var kdr in topKDRs)
{
string kdrString = kdr.KDR.ToString("0.0").PadRight(5);
message += $"<color=#ff686b>{kdrString}</color>| {kdr.Name}\n";
}
SendReply(player, message);
}
void SendReply(BasePlayer player, string message)
{
player.ChatMessage(message);
}
bool IsValidSteamID(ulong userID)
{
string userIDString = userID.ToString();
return userIDString.StartsWith("7656") && userIDString.Length == 17;
}
}
}