C#:
using System;
using System.Linq;
using System.Globalization;
using System.Collections.Generic;
using UnityEngine;
using Oxide.Core;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;
using Oxide.Core.Libraries.Covalence;
namespace Oxide.Plugins
{
[Info("CPlayerStats", "Crazy", "1.1.1")]
[Description("Simple players PVP data on wipe.")]
class CPlayerStats : RustPlugin
{
#region Fields
[PluginReference] private Plugin ImageLibrary;
private static CPlayerStats _ins;
private static string permView = "cplayerstats.view";
private string imgKill = "https://i49.servimg.com/u/f49/14/08/21/53/kill12.png";
private string imgDeath = "https://i49.servimg.com/u/f49/14/08/21/53/death12.png";
private string imgDiscord = "https://i49.servimg.com/u/f49/14/08/21/53/discor10.png";
private static string discord = "discord.gg/5NtNRhU";
private static Dictionary<ulong, PStats> pStats = new Dictionary<ulong, PStats>();
private static Dictionary<ulong, UIStats> data = new Dictionary<ulong, UIStats>();
#endregion
#region Server
private void OnServerInitialized()
{
_ins = this;
if (!ImageLibrary)
{
PrintError("ImageLibrary not found, plugin will not work!");
return;
}
ImageLibrary.Call("AddImage", imgKill, "cplayerstats.img.kill");
ImageLibrary.Call("AddImage", imgDeath, "cplayerstats.img.death");
ImageLibrary.Call("AddImage", imgDiscord, "cplayerstats.img.discord");
permission.RegisterPermission(permView, this);
foreach (BasePlayer player in BasePlayer.activePlayerList)
OnPlayerConnected(player);
}
private void OnPlayerConnected(BasePlayer player)
{
if (player.IsReceivingSnapshot || player.IsSleeping())
{
timer.In(2, () => OnPlayerConnected(player));
return;
}
PStats.TryLoad(player.userID);
if (!player.GetComponent<UIStats>())
data[player.userID] = player.gameObject.AddComponent<UIStats>();
}
private void OnPlayerDeath(BasePlayer victim, HitInfo info)
{
BasePlayer killer = info?.Initiator as BasePlayer;
if (killer == null || killer == victim)
return;
if (victim.IsNpc || killer.IsNpc)
return;
if (pStats.ContainsKey(killer.userID))
pStats[killer.userID].kills++;
if (pStats.ContainsKey(victim.userID))
pStats[victim.userID].deaths++;
return;
}
private void OnServerShutDown() => Unload();
private void Unload()
{
foreach (var s in pStats)
s.Value.Save(s.Key);
if (BasePlayer.activePlayerList.Count == 0)
return;
UIStats[] objects = UnityEngine.Object.FindObjectsOfType<UIStats>();
if (objects != null)
{
foreach (var obj in objects)
UnityEngine.Object.Destroy(obj);
}
}
private void OnPlayerDisconnected(BasePlayer player)
{
if(data.ContainsKey(player.userID))
UnityEngine.Object.Destroy(data[player.userID]);
}
private void OnNewSave(string filename) => GetAllPlayers().ForEach(ID => PStats.Reset(ID));
#endregion
#region Component
private class UIStats : FacepunchBehaviour
{
public int kills;
public int deaths;
public bool needUpdate;
private BasePlayer player;
private void Awake()
{
player = GetComponent<BasePlayer>();
Instance();
InvokeRepeating(Refresh, 0f, 1);
}
private void Instance()
{
kills = pStats[player.userID].kills;
deaths = pStats[player.userID].deaths;
needUpdate = false;
DestroyUI();
CreateUI();
}
private void Refresh()
{
if(kills != pStats[player.userID].kills || deaths != pStats[player.userID].deaths)
needUpdate = true;
if(needUpdate && player.IPlayer.HasPermission(permView))
{
Instance();
return;
}
}
private void CreateUI()
{
if(player.IPlayer.HasPermission(permView))
{
var containerKill = UI.CreateElementContainer("cplayerstats.kills", "1 1 1 0.1", "0.045 0.003", "0.075 0.025");
UI.AddImage(ref containerKill, "cplayerstats.kills", 0.3f, "cplayerstats.img.kill", "1 1 1 0.3", "0 -0.1", "0.5 1", "0 1", "0 1");
UI.AddImageColor(ref containerKill, "cplayerstats.kills", HexToRustFormat("#aabf7daf"), "0.55 0.1", "0.955 0.9", "0 0", "0 0");
UI.AddText(ref containerKill, "cplayerstats.kills", kills.ToString(), 9, "robotocondensed-regular.ttf", "1 1 1 0.8", TextAnchor.MiddleCenter, "0.50 0.0", "1.0 1");
CuiHelper.AddUi(player, containerKill);
var containerDeath = UI.CreateElementContainer("cplayerstats.deaths", "1 1 1 0.1", "0.08 0.003", "0.11 0.025");
UI.AddImage(ref containerDeath, "cplayerstats.deaths", 0.3f, "cplayerstats.img.death", "1 1 1 0.3", "0 -0.1", "0.5 1", "0 1", "0 1");
UI.AddImageColor(ref containerDeath, "cplayerstats.deaths", HexToRustFormat("#d8453daf"), "0.55 0.1", "0.955 0.9", "0 0", "0 0");
UI.AddText(ref containerDeath, "cplayerstats.deaths", deaths.ToString(), 9, "robotocondensed-regular.ttf", "1 1 1 0.8", TextAnchor.MiddleCenter, "0.50 0.0", "1.0 1");
CuiHelper.AddUi(player, containerDeath);
}
else
{
var containerDiscord = UI.CreateElementContainer("cplayerstats.discord", "1 1 1 0.1", "0.045 0.003", "0.12 0.025");
UI.AddImage(ref containerDiscord, "cplayerstats.discord", 0.3f, "cplayerstats.img.discord", "1 1 1 0.3", "0 -0.1", "0.17 1", "0 1", "0 1");
UI.AddImageColor(ref containerDiscord, "cplayerstats.discord", HexToRustFormat("#bf8e51a1"), "0.20 0.1", "0.98 0.9", "0 0", "0 0");
UI.AddText(ref containerDiscord, "cplayerstats.discord", discord, 9, "robotocondensed-regular.ttf", "1 1 1 0.8", TextAnchor.MiddleCenter, "0.18 0.0", "1.0 1");
CuiHelper.AddUi(player, containerDiscord);
}
}
private void DestroyUI()
{
CuiHelper.DestroyUi(player, "cplayerstats.kills");
CuiHelper.DestroyUi(player, "cplayerstats.deaths");
CuiHelper.DestroyUi(player, "cplayerstats.discord");
}
private void OnDestroy() => DestroyUI();
}
#endregion
#region UI
static class UI
{
static public CuiElementContainer CreateElementContainer(string panel, string color, string aMin, string aMax)
{
var NewElement = new CuiElementContainer()
{
{
new CuiPanel
{
Image = {Color = color},
RectTransform = {AnchorMin = aMin, AnchorMax = aMax}
},
new CuiElement().Parent = "Hud",
panel
}
};
return NewElement;
}
static public void AddText(ref CuiElementContainer container, string panel, string text, int size, string font, string color, TextAnchor align, string aMin, string aMax)
{
container.Add(new CuiElement
{
Name = CuiHelper.GetGuid(),
Parent = panel,
Components =
{
new CuiTextComponent
{
Text = text, FontSize = size,
Font = font,
Color = color,
Align = align
},
new CuiRectTransformComponent {
AnchorMin = aMin,
AnchorMax = aMax
}
}
});
}
static public void AddImageColor(ref CuiElementContainer container, string panel, string color, string aMin, string aMax, string oMin, string oMax)
{
container.Add(new CuiElement
{
Name = CuiHelper.GetGuid(),
Parent = panel,
Components =
{
new CuiImageComponent
{
Color = color
},
new CuiRectTransformComponent {
AnchorMin = aMin,
AnchorMax = aMax,
OffsetMin = oMin,
OffsetMax = oMax
}
}
});
}
static public void AddImage(ref CuiElementContainer container, string panel, float fade, string imgName, string color, string aMin, string aMax, string oMin, string oMax)
{
container.Add(new CuiElement
{
Name = CuiHelper.GetGuid(),
Parent = panel,
Components =
{
new CuiRawImageComponent
{
FadeIn = fade,
Color = color,
Png = (string) _ins.ImageLibrary.Call("GetImage", imgName),
Sprite = "assets/content/textures/generic/fulltransparent.tga",
},
new CuiRectTransformComponent
{
AnchorMin = aMin,
AnchorMax = aMax,
OffsetMin = oMin,
OffsetMax = oMax
}
}
});
}
}
#endregion
#region Helpers
private static string HexToRustFormat(string hex)
{
if (string.IsNullOrEmpty(hex))
hex = "#FFFFFFFF";
var str = hex.Trim('#');
if (str.Length == 6)
str += "FF";
if (str.Length != 8)
{
throw new Exception(hex);
throw new InvalidOperationException("Cannot convert a wrong format.");
}
var r = byte.Parse(str.Substring(0, 2), NumberStyles.HexNumber);
var g = byte.Parse(str.Substring(2, 2), NumberStyles.HexNumber);
var b = byte.Parse(str.Substring(4, 2), NumberStyles.HexNumber);
var a = byte.Parse(str.Substring(6, 2), NumberStyles.HexNumber);
Color color = new Color32(r, g, b, a);
return string.Format("{0:F2} {1:F2} {2:F2} {3:F2}", color.r, color.g, color.b, color.a);
}
#endregion
#region Functions
public List<ulong> GetAllPlayers()
{
List<ulong> playerID = new List<ulong>();
covalence.Players.All.ToList().ForEach(IPlayer => playerID.Add(ulong.Parse(IPlayer.Id)));
return playerID;
}
#endregion
#region Data
private class PStats
{
public int kills;
public int deaths;
internal static void TryLoad(ulong id)
{
if(pStats.ContainsKey(id))
return;
PStats data = Interface.Oxide.DataFileSystem.ReadObject<PStats>($"CPlayerStats/{id}");
if(data == null)
data = new PStats();
pStats.Add(id, data);
}
internal static void Reset(ulong id)
{
PStats data = Interface.Oxide.DataFileSystem.ReadObject<PStats>($"CPlayerStats/{id}");
if(data == null)
return;
data = new PStats();
data.Save(id);
}
internal void Save(ulong id) => Interface.Oxide.DataFileSystem.WriteObject(($"CPlayerStats/{id}"), this, true);
}
#endregion
}
}