C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
/***********************************************************************************************************************/
/*** DO NOT edit this file! Edit the files under `oxide/config` and/or `oxide/lang`, created once plugin has loaded.***/
/*** Please note, support cannot be provided if the plugin has been modified.Please use a fresh copy if modified.***/
/***********************************************************************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using MySql.Data.MySqlClient;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Oxide.Core;
using Oxide.Core.Configuration;
using Oxide.Core.Database;
using Oxide.Core.Libraries;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;
using Rust;
using UnityEngine;
namespace Oxide.Plugins {
[Info("Kill Records", "MACHIN3", "1.3.800")]
[Description("Records number of kills by each player for selected entities")]
public class KillRecords : RustPlugin {
public const string version = "1.3.800";
#region Update Log
/*****************************************************
【 𝓜𝓐𝓒𝓗𝓘𝓝𝓔 】
Website: https://www.rustlevels.com/
Discord: http://discord.rustlevels.com/
*****************************************************/
#region 1.3.8
/*
✯ Fixed Patrol Helicopter not being tracked
✯ Fixed Animal Harvest not being tracked
✯ Fixed Human Harvest not being tracked
✯ Fixed wolf tracking with new wolf AI
NOTES:
* Report any issues in our discord
*/
#endregion
#region 1.3.7
/*
✯ Fixed data loading issues due to last major update
NOTES:
* There is a known issue with NightZombies mod not counting some kills which is still being worked on
*/
#endregion
#region 1.3.6
/*
✯ Version 1.3.6
✯ New special character ignore method for SQL usage
✯ Possible fix for SQL NRE errors
✯ Fix for Rust May Update
*/
#endregion
#region 1.3.5
/*
✯ update 1.3.5
✯ Updated for OnCollectiblePickup hook changes
*/
#endregion
#region 1.3.4
/*
✯ update 1.3.4
✯ Fixed OnEntityDeath error from turrets
*/
#endregion
#region 1.3.3
/*
✯ update 1.3.3
✯ Added Scare Crow tracking
✯ Added Turret Tracking
✯ Code cleanup
*/
#endregion
#region 1.3.2
/*
✯ update 1.3.2
✯ Fixed non players being added to data records
✯ Will automatically remove any non valid steam players from records
*/
#endregion
#region 1.3.1
/*
✯ update 1.3.1
✯ Fixed SQL issues with adding Polar Bear tracking
✯ All chat commands are now configurable
✯ Added harvest API for XPerience and XPerienceAddon
✯ New SQL update method for creating new columns in existing SQL database
New Harvest Tracking:
✯ Trees cut
✯ Ore mined
✯ Wood pickup
✯ Ore pickup
✯ Berries
✯ Pumpkins
✯ Potatos
✯ Corn
✯ Mushrrom
✯ Hemp
✯ Seeds
Harvest tracking will only count the number of harvests NOT total resources gathered! XPerience will track total amount harvested.*/
#endregion
#region 1.3.0
/*
✯ update 1.3.0
✯ Fixed horse kills not counting
✯ Added PolarBear Tracking
*/
#endregion
#region 1.2.9
/*
✯ update 1.2.9
✯ Fixed scientists kills not counting
*/
#endregion
#region 1.2.8
/*
✯ update 1.2.8
✯ Cleaned up coding
✯ Added API needed for XPerienceAddon
*/
#endregion
#region 1.2.7
/*
✯ update 1.2.7
✯ Fixed SQL update issues
*/
#endregion
#region 1.2.6
/*
✯ update 1.2.6
✯ Improved code performance
*/
#endregion
#region 1.2.5
/*
✯ update 1.2.5
✯ Added BradleyAPC and Patrol Helicopter tracking
*/
#endregion
#region 1.2.4
/*
✯ update 1.2.4
✯ Added UINotify Support
✯ Complete rewrite of config file and settings
✯ Changed OnFishCaught to OnFishCatch so fish tracking works again
*/
#endregion
#region 1.2.3
/*
✯ update 1.2.3
✯ Added Fish tracking
*/
#endregion
#region 1.2.2
/*
✯ update 1.2.2
✯ fixed SQL errors with player displayname
✯ fixed players not being able to disable chat messages when given permission
✯ fix for onplayerdeath error
*/
#endregion
#region 1.2.1
/*
✯ this update 1.2.1
✯ fixed possible player search issues when using SQL
✯ fixed issues with SQL not tracking stats
✯ added support for ImageLibrary for player avatars
✯ added new leaderboards UI
✯ linked all UIs with buttons
✯ names in all UIs now clickable to player stats
✯ added option to manually order each entity in UIs
✯ added command to clear all player data
*/
#endregion
#region 1.2.0
/*
✯ update 1.2.0
✯ fixed top ten list showing players with 0
✯ new global kill stats
✯ option to disable UI
✯ rewrote top list with selection menu
✯ SQL support
✯ New commands (datafile save, sql save, etc..)
✯ Added horse kill tracking
*/
#endregion
#region 1.1.9
/*
✯ update 1.1.9
✯ cleaned coding
✯ fixed killchat permission
✯ More chat argument definitions
✯ Added animal/corpse harvest to top lists
*/
#endregion
#region 1.1.8
/*
✯ update 1.1.8
✯ Changed UI locations
✯ rewrote webrequest & labels
✯ Changed star to arrow on top list
✯ Rewrote language and chat messages
✯ Full language support
✯ Option to limit kill messages
✯ Permissions to disable kill messages
✯ Option for players to disable kill messages
✯ More chat argument definitions
*/
#endregion
#endregion
#region References
[PluginReference]
private readonly Plugin ImageLibrary, UINotify;
#endregion
#region Fields
private PlayData _playData;
private TempData _tempData;
private HeliHits _heliHits;
private DynamicConfigFile _KillData;
private DynamicConfigFile _EntityData;
private Dictionary<string, Record> _recordCache;
private Dictionary<ulong, Data> _dataCache;
private Dictionary<ulong, Heli> _heliCache;
private Configuration config;
private const string KRUIName = "KillRecordsUI";
private const string KRUIMainName = "KillRecordsUIMain";
private const string KRUISelection = "KillRecordsUISelection";
private const string Admin = "killrecords.admin";
private const string Killchat = "killrecords.killchat";
private Timer _helitracker;
#endregion
#region Config
private class Configuration : SerializableConfiguration {
[JsonProperty("Tracking Options")]
public TrackingOptions trackingoptions = new TrackingOptions();
[JsonProperty("Player Chat Commands")]
public PlayerChatCommands playerChatCommands = new PlayerChatCommands();
[JsonProperty("Admin Chat Commands")]
public AdminChatCommands adminChatCommands = new AdminChatCommands();
[JsonProperty("Harvest Options")]
public HarvestOptions harvestoptions = new HarvestOptions();
[JsonProperty("Order Options")]
public OrderOptions orderoptions = new OrderOptions();
[JsonProperty("Chat & UI Options")]
public ChatUI chatui = new ChatUI();
[JsonProperty("Web Request")]
public WebRequest webrequest = new WebRequest();
[JsonProperty("SQL")]
public KRSQL krsql = new KRSQL();
}
public class PlayerChatCommands {
public string krhelp = "krhelp";
public string pkills = "pkills";
public string pkillschat = "pkillschat";
public string topkills = "topkills";
public string topkillschat = "topkillschat";
public string totalkills = "totalkills";
public string totalkillschat = "totalkillschat";
public string leadkills = "leadkills";
public string pstats = "pstats";
public string pstatschat = "pstatschat";
public string topstats = "topstats";
public string totalstats = "totalstats";
public string totalstatschat = "totalstatschat";
public string killchat = "killchat";
}
public class AdminChatCommands {
public string krhelpadmin = "krhelpadmin";
public string krweb = "krweb";
public string krsql = "krsql";
public string krbackup = "krbackup";
public string krreset = "krreset";
}
private class TrackingOptions {
public bool Trackchicken = true;
public bool Trackboar = true;
public bool Trackstag = true;
public bool Trackwolf = true;
public bool Trackbear = true;
public bool Trackpolarbear = true;
public bool Trackshark = true;
public bool Trackhorse = true;
public bool Trackfish = true;
public bool TrackPlayer = true;
public bool Trackscientist = true;
public bool Trackscarecrow = true;
public bool Trackdweller = true;
public bool Tracklootcontainer = true;
public bool Trackunderwaterlootcontainer = true;
public bool Trackbradhelicrate = true;
public bool Trackhackablecrate = true;
public bool Trackdeaths = true;
public bool Tracksuicides = true;
public bool TrackAnimalHarvest = true;
public bool TrackCorpseHarvest = true;
public bool TrackBradley = true;
public bool TrackHeli = true;
public bool Trackturret = true;
public bool Trackzombie = true;
}
private class HarvestOptions {
public bool treescut = true;
public bool oremined= true;
public bool cactuscut= false;
public bool woodpickup= true;
public bool orepickup= true;
public bool berriespickup= true;
public bool pumpkinpickup= true;
public bool potatopickup= true;
public bool cornpickup= true;
public bool mushroompickup= true;
public bool hemppickup= true;
public bool seedpickup= true;
}
private class OrderOptions {
public int chickenpos = 1;
public int boarpos = 2;
public int stagpos = 3;
public int wolfpos = 4;
public int bearpos = 5;
public int polarbearpos = 22;
public int sharkpos = 6;
public int horsepos = 7;
public int fishpos = 19;
public int playerpos = 8;
public int scientistpos = 9;
public int dwellerpos = 10;
public int lootpos = 11;
public int unlootpos = 12;
public int bradhelicratepos = 13;
public int hackablecratepos = 14;
public int deathpos = 15;
public int suicidepos = 16;
public int corpsepos = 17;
public int pcorpsepos = 18;
public int bradleypos = 20;
public int helipos = 21;
public int scarecrowpos = 23;
public int turretpos = 24;
}
private class ChatUI {
public bool enableui = true;
public bool UseImageLibrary = false;
public bool ShowKillMessages = true;
public int KillMessageInterval = 1;
public int KillMessageLimit = 5000;
public bool enableuinotify = false;
public bool disablechats = false;
public int uinotifytype = 0;
}
private class WebRequest {
public bool UseWebrequests = false;
public string DataURL = "URL";
public string SecretKey = "SecretKey";
}
private class KRSQL {
public bool UseSQL = false;
public int FileType = 0;
public string SQLhost = "localhost";
public int SQLport = 3306;
public string SQLdatabase = "databasename";
public string SQLusername = "username";
public string SQLpassword = "password";
}
protected override void LoadDefaultConfig() => config = new Configuration();
protected override void LoadConfig() {
base.LoadConfig();
try {
config = Config.ReadObject<Configuration>();
if (config == null) {
throw new JsonException();
}
if (MaybeUpdateConfig(config)) {
PrintWarning("Configuration appears to be outdated; updating and saving");
SaveConfig();
}
}
catch {
PrintWarning($"Configuration file {Name}.json is invalid; using defaults");
LoadDefaultConfig();
}
}
protected override void SaveConfig() {
PrintWarning($"Configuration changes saved to {Name}.json");
Config.WriteObject(config, true);
}
#endregion
#region UpdateChecker
internal class SerializableConfiguration {
public string ToJson() => JsonConvert.SerializeObject(this);
public Dictionary<string, object> ToDictionary() => JsonHelper.Deserialize(ToJson()) as Dictionary<string, object>;
}
private static class JsonHelper {
public static object Deserialize(string json) => ToObject(JToken.Parse(json));
private static object ToObject(JToken token) {
switch (token.Type) {
case JTokenType.Object : return token.Children<JProperty>().ToDictionary(prop => prop.Name, prop => ToObject(prop.Value));
case JTokenType.Array : return token.Select(ToObject).ToList();
default : return ((JValue)token).Value;
}
}
}
private bool MaybeUpdateConfig(SerializableConfiguration config) {
var currentWithDefaults = config.ToDictionary();
var currentRaw = Config.ToDictionary(x => x.Key, x => x.Value);
return MaybeUpdateConfigDict(currentWithDefaults, currentRaw);
}
private bool MaybeUpdateConfigDict(Dictionary<string, object> currentWithDefaults, Dictionary<string, object> currentRaw) {
bool changed = false;
foreach (var key in currentWithDefaults.Keys) {
object currentRawValue;
if (currentRaw.TryGetValue(key, out currentRawValue)) {
var defaultDictValue = currentWithDefaults[key] as Dictionary<string, object>;
var currentDictValue = currentRawValue as Dictionary<string, object>;
if (defaultDictValue != null) {
if (currentDictValue == null) {
currentRaw[key] = currentWithDefaults[key];
changed = true;
}
else if (MaybeUpdateConfigDict(defaultDictValue, currentDictValue)) changed = true;
}
}
else {
currentRaw[key] = currentWithDefaults[key];
changed = true;
}
}
return changed;
}
#endregion
#region Storage
private void SaveData() {
if (_playData != null) {
_playData.KillRecords = _recordCache;
_KillData.WriteObject(_playData);
}
}
private void SaveTemp() {
_EntityData = Interface.Oxide.DataFileSystem.GetFile(nameof(KillRecords) + "/KillRecordsEntityData");
_dataCache.Clear();
if (_tempData != null) {
_tempData.EntityRecords = _dataCache;
_EntityData.WriteObject(_tempData);
}
}
private void LoadData() {
try {
_playData = _KillData.ReadObject<PlayData>();
_recordCache = _playData.KillRecords;
}
catch {
_playData = new PlayData();
}
try {
_tempData = _EntityData.ReadObject<TempData>();
_dataCache = _tempData.EntityRecords;
}
catch {
_tempData = new TempData();
}
}
private class TempData {
public Dictionary<ulong, Data> EntityRecords = new Dictionary<ulong, Data>();
}
private class Data {
public ulong entity;
public List<string> id;
}
private class PlayData {
public Dictionary<string, Record> KillRecords = new Dictionary<string, Record>();
}
private class Record {
public int chicken;
public int boar;
public int stag;
public int wolf;
public int bear;
public int polarbear;
public int shark;
public int horse;
public int fish;
public int scientistnpcnew;
public int scarecrow;
public int dweller;
public int baseplayer;
public int basecorpse;
public int npcplayercorpse;
public int zombie;
public int deaths;
public int suicides;
public int lootcontainer;
public int underwaterlootcontainer;
public int bradhelicrate;
public int hackablecrate;
public int bradley;
public int heli;
public int turret;
public string displayname;
public string id;
public bool killchat;
public int treescut;
public int oremined;
public int cactuscut;
public int woodpickup;
public int orepickup;
public int berriespickup;
public int pumpkinpickup;
public int potatopickup;
public int cornpickup;
public int mushroompickup;
public int hemppickup;
public int seedpickup;
}
private class HeliHits {
public Dictionary<ulong, Heli> HeliRecords = new Dictionary<ulong, Heli>();
}
private class Heli {
public ulong heli;
public ulong player;
}
#endregion
#region SQL
private string RemoveSpecialCharacters(string name) {
string newname = Regex.Replace(name, @"[^0-9a-zA-Z]+", "");
return newname;
}
private readonly Core.MySql.Libraries.MySql sqlLibrary = Interface.Oxide.GetLibrary<Core.MySql.Libraries.MySql>();
Connection sqlConnection;
//SQL Table
private void CreatSQLTable() {
sqlLibrary.Insert(Sql.Builder.Append($"CREATE TABLE IF NOT EXISTS KillRecords (" + $" `id` BIGINT(255) NOT NULL AUTO_INCREMENT," + $" `steamid` BIGINT(255) NOT NULL," + $" `displayname` VARCHAR(255) NOT NULL," + $" `chicken` BIGINT(255) NOT NULL DEFAULT '0'," + $" `boar` BIGINT(255) NOT NULL DEFAULT '0'," + $" `stag` BIGINT(255) NOT NULL DEFAULT '0'," + $" `wolf` BIGINT(255) NOT NULL DEFAULT '0'," + $" `bear` BIGINT(255) NOT NULL DEFAULT '0'," + $" `polarbear` BIGINT(255) NOT NULL DEFAULT '0'," + $" `shark` BIGINT(255) NOT NULL DEFAULT '0'," + $" `horse` BIGINT(255) NOT NULL DEFAULT '0'," + $" `fish` BIGINT(255) NOT NULL DEFAULT '0'," + $" `scientistnpcnew` BIGINT(255) NOT NULL DEFAULT '0'," + $" `scarecrow` BIGINT(255) NOT NULL DEFAULT '0'," + $" `dweller` BIGINT(255) NOT NULL DEFAULT '0'," + $" `baseplayer` BIGINT(255) NOT NULL DEFAULT '0'," + $" `basecorpse` BIGINT(255) NOT NULL DEFAULT '0'," + $" `npcplayercorpse` BIGINT(255) NOT NULL DEFAULT '0'," + $" `zombie` BIGINT(255) NOT NULL DEFAULT '0'," + $" `deaths` BIGINT(255) NOT NULL DEFAULT '0'," + $" `suicides` BIGINT(255) NOT NULL DEFAULT '0'," + $" `lootcontainer` BIGINT(255) NOT NULL DEFAULT '0'," + $" `bradhelicrate` BIGINT(255) NOT NULL DEFAULT '0'," + $" `hackablecrate` BIGINT(255) NOT NULL DEFAULT '0'," + $" `bradley` BIGINT(255) NOT NULL DEFAULT '0'," + $" `heli` BIGINT(255) NOT NULL DEFAULT '0'," + $" `turret` BIGINT(255) NOT NULL DEFAULT '0'," + $" `underwaterlootcontainer` BIGINT(255) NOT NULL DEFAULT '0'," + $" `killchat` VARCHAR(255) NOT NULL DEFAULT 'True'," + $" `treescut` BIGINT(255) NOT NULL DEFAULT '0'," + $" `oremined` VARCHAR(255) NOT NULL DEFAULT '0'," + $" `cactuscut` VARCHAR(255) NOT NULL DEFAULT '0'," + $" `woodpickup` VARCHAR(255) NOT NULL DEFAULT '0'," + $" `orepickup` VARCHAR(255) NOT NULL DEFAULT '0'," + $" `berriespickup` VARCHAR(255) NOT NULL DEFAULT '0'," + $" `pumpkinpickup` VARCHAR(255) NOT NULL DEFAULT '0'," + $" `potatopickup` VARCHAR(255) NOT NULL DEFAULT '0'," + $" `cornpickup` VARCHAR(255) NOT NULL DEFAULT '0'," + $" `mushroompickup` VARCHAR(255) NOT NULL DEFAULT '0'," + $" `hemppickup` VARCHAR(255) NOT NULL DEFAULT '0'," + $" `seedpickup` VARCHAR(255) NOT NULL DEFAULT '0'," + $"PRIMARY KEY (id)" + $" );"), sqlConnection);
}
private void UpdateSQLTable() {
try {
bool treescut = false;
bool oremined = false;
bool cactuscut = false;
bool woodpickup = false;
bool orepickup = false;
bool berriespickup = false;
bool pumpkinpickup = false;
bool potatopickup = false;
bool cornpickup = false;
bool mushroompickup = false;
bool hemppickup = false;
bool seedpickup = false;
bool polarbear = false;
bool bradley = false;
bool heli = false;
bool scarecrow = false;
bool turret = false;
bool zombie = false;
sqlLibrary.Query(Sql.Builder.Append($"SELECT * FROM KillRecords"), sqlConnection, list => {
foreach (var entry in list) {
if (!entry.ContainsKey("zombie")) {
//sqlLibrary.Insert(Sql.Builder.Append($"ALTER TABLE KillRecords ADD COLUMN `treescut` BIGINT(255) NOT NULL DEFAULT '0' AFTER killchat"), sqlConnection);
zombie = true;
}
if (!entry.ContainsKey("treescut")) {
//sqlLibrary.Insert(Sql.Builder.Append($"ALTER TABLE KillRecords ADD COLUMN `treescut` BIGINT(255) NOT NULL DEFAULT '0' AFTER killchat"), sqlConnection);
treescut = true;
}
if (!entry.ContainsKey("oremined")) {
//sqlLibrary.Insert(Sql.Builder.Append($"ALTER TABLE KillRecords ADD COLUMN `oremined` BIGINT(255) NOT NULL DEFAULT '0' AFTER treescut"), sqlConnection);
oremined = true;
}
if (!entry.ContainsKey("cactuscut")) {
//sqlLibrary.Insert(Sql.Builder.Append($"ALTER TABLE KillRecords ADD COLUMN `cactuscut` BIGINT(255) NOT NULL DEFAULT '0' AFTER oremined"), sqlConnection);
cactuscut = true;
}
if (!entry.ContainsKey("woodpickup")) {
//sqlLibrary.Insert(Sql.Builder.Append($"ALTER TABLE KillRecords ADD COLUMN `woodpickup` BIGINT(255) NOT NULL DEFAULT '0' AFTER cactuscut"), sqlConnection);
woodpickup = true;
}
if (!entry.ContainsKey("orepickup")) {
//sqlLibrary.Insert(Sql.Builder.Append($"ALTER TABLE KillRecords ADD COLUMN `orepickup` BIGINT(255) NOT NULL DEFAULT '0' AFTER woodpickup"), sqlConnection);
orepickup = true;
}
if (!entry.ContainsKey("berriespickup")) {
//sqlLibrary.Insert(Sql.Builder.Append($"ALTER TABLE KillRecords ADD COLUMN `berriespickup` BIGINT(255) NOT NULL DEFAULT '0' AFTER orepickup"), sqlConnection);
berriespickup = true;
}
if (!entry.ContainsKey("pumpkinpickup")) {
//sqlLibrary.Insert(Sql.Builder.Append($"ALTER TABLE KillRecords ADD COLUMN `pumpkinpickup` BIGINT(255) NOT NULL DEFAULT '0' AFTER berriespickup"), sqlConnection);
pumpkinpickup = true;
}
if (!entry.ContainsKey("potatopickup")) {
//sqlLibrary.Insert(Sql.Builder.Append($"ALTER TABLE KillRecords ADD COLUMN `potatopickup` BIGINT(255) NOT NULL DEFAULT '0' AFTER pumpkinpickup"), sqlConnection);
potatopickup = true;
}
if (!entry.ContainsKey("cornpickup")) {
//sqlLibrary.Insert(Sql.Builder.Append($"ALTER TABLE KillRecords ADD COLUMN `cornpickup` BIGINT(255) NOT NULL DEFAULT '0' AFTER potatopickup"), sqlConnection);
cornpickup = true;
}
if (!entry.ContainsKey("mushroompickup")) {
//sqlLibrary.Insert(Sql.Builder.Append($"ALTER TABLE KillRecords ADD COLUMN `mushroompickup` BIGINT(255) NOT NULL DEFAULT '0' AFTER cornpickup"), sqlConnection);
mushroompickup = true;
}
if (!entry.ContainsKey("hemppickup")) {
//sqlLibrary.Insert(Sql.Builder.Append($"ALTER TABLE KillRecords ADD COLUMN `hemppickup` BIGINT(255) NOT NULL DEFAULT '0' AFTER mushroompickup"), sqlConnection);
hemppickup = true;
}
if (!entry.ContainsKey("seedpickup")) {
//sqlLibrary.Insert(Sql.Builder.Append($"ALTER TABLE KillRecords ADD COLUMN `seedpickup` BIGINT(255) NOT NULL DEFAULT '0' AFTER hemppickup"), sqlConnection);
seedpickup = true;
}
if (!entry.ContainsKey("polarbear")) {
//sqlLibrary.Insert(Sql.Builder.Append($"ALTER TABLE KillRecords ADD COLUMN `polarbear` BIGINT(255) NOT NULL DEFAULT '0' AFTER bear"), sqlConnection);
polarbear = true;
}
if (!entry.ContainsKey("bradley")) {
//sqlLibrary.Insert(Sql.Builder.Append($"ALTER TABLE KillRecords ADD COLUMN `bradley` BIGINT(255) NOT NULL DEFAULT '0' AFTER hackablecrate"), sqlConnection);
bradley = true;
}
if (!entry.ContainsKey("heli")) {
//sqlLibrary.Insert(Sql.Builder.Append($"ALTER TABLE KillRecords ADD COLUMN `heli` BIGINT(255) NOT NULL DEFAULT '0' AFTER bradley"), sqlConnection);
heli = true;
}
if (!entry.ContainsKey("scarecrow")) {
//sqlLibrary.Insert(Sql.Builder.Append($"ALTER TABLE KillRecords ADD COLUMN `scarecrow` BIGINT(255) NOT NULL DEFAULT '0' AFTER scientistnpcnew"), sqlConnection);
scarecrow = true;
}
if (!entry.ContainsKey("turret")) {
//sqlLibrary.Insert(Sql.Builder.Append($"ALTER TABLE KillRecords ADD COLUMN `turret` BIGINT(255) NOT NULL DEFAULT '0' AFTER heli"), sqlConnection);
turret = true;
}
}
if (zombie) {
sqlLibrary.Insert(Sql.Builder.Append($"ALTER TABLE KillRecords ADD COLUMN `zombie` BIGINT(255) NOT NULL DEFAULT '0' AFTER npcplayercorpse"), sqlConnection);
}
if (treescut) {
sqlLibrary.Insert(Sql.Builder.Append($"ALTER TABLE KillRecords ADD COLUMN `treescut` BIGINT(255) NOT NULL DEFAULT '0' AFTER killchat"), sqlConnection);
}
if (oremined) {
sqlLibrary.Insert(Sql.Builder.Append($"ALTER TABLE KillRecords ADD COLUMN `oremined` BIGINT(255) NOT NULL DEFAULT '0' AFTER treescut"), sqlConnection);
}
if (cactuscut) {
sqlLibrary.Insert(Sql.Builder.Append($"ALTER TABLE KillRecords ADD COLUMN `cactuscut` BIGINT(255) NOT NULL DEFAULT '0' AFTER oremined"), sqlConnection);
}
if (woodpickup) {
sqlLibrary.Insert(Sql.Builder.Append($"ALTER TABLE KillRecords ADD COLUMN `woodpickup` BIGINT(255) NOT NULL DEFAULT '0' AFTER cactuscut"), sqlConnection);
}
if (orepickup) {
sqlLibrary.Insert(Sql.Builder.Append($"ALTER TABLE KillRecords ADD COLUMN `orepickup` BIGINT(255) NOT NULL DEFAULT '0' AFTER woodpickup"), sqlConnection);
}
if (berriespickup) {
sqlLibrary.Insert(Sql.Builder.Append($"ALTER TABLE KillRecords ADD COLUMN `berriespickup` BIGINT(255) NOT NULL DEFAULT '0' AFTER orepickup"), sqlConnection);
}
if (pumpkinpickup) {
sqlLibrary.Insert(Sql.Builder.Append($"ALTER TABLE KillRecords ADD COLUMN `pumpkinpickup` BIGINT(255) NOT NULL DEFAULT '0' AFTER berriespickup"), sqlConnection);
}
if (potatopickup) {
sqlLibrary.Insert(Sql.Builder.Append($"ALTER TABLE KillRecords ADD COLUMN `potatopickup` BIGINT(255) NOT NULL DEFAULT '0' AFTER pumpkinpickup"), sqlConnection);
}
if (cornpickup) {
sqlLibrary.Insert(Sql.Builder.Append($"ALTER TABLE KillRecords ADD COLUMN `cornpickup` BIGINT(255) NOT NULL DEFAULT '0' AFTER potatopickup"), sqlConnection);
}
if (mushroompickup) {
sqlLibrary.Insert(Sql.Builder.Append($"ALTER TABLE KillRecords ADD COLUMN `mushroompickup` BIGINT(255) NOT NULL DEFAULT '0' AFTER cornpickup"), sqlConnection);
}
if (hemppickup) {
sqlLibrary.Insert(Sql.Builder.Append($"ALTER TABLE KillRecords ADD COLUMN `hemppickup` BIGINT(255) NOT NULL DEFAULT '0' AFTER mushroompickup"), sqlConnection);
}
if (seedpickup) {
sqlLibrary.Insert(Sql.Builder.Append($"ALTER TABLE KillRecords ADD COLUMN `seedpickup` BIGINT(255) NOT NULL DEFAULT '0' AFTER hemppickup"), sqlConnection);
}
if (polarbear) {
sqlLibrary.Insert(Sql.Builder.Append($"ALTER TABLE KillRecords ADD COLUMN `polarbear` BIGINT(255) NOT NULL DEFAULT '0' AFTER bear"), sqlConnection);
}
if (bradley) {
sqlLibrary.Insert(Sql.Builder.Append($"ALTER TABLE KillRecords ADD COLUMN `bradley` BIGINT(255) NOT NULL DEFAULT '0' AFTER hackablecrate"), sqlConnection);
}
if (heli) {
sqlLibrary.Insert(Sql.Builder.Append($"ALTER TABLE KillRecords ADD COLUMN `heli` BIGINT(255) NOT NULL DEFAULT '0' AFTER bradley"), sqlConnection);
}
if (scarecrow) {
sqlLibrary.Insert(Sql.Builder.Append($"ALTER TABLE KillRecords ADD COLUMN `scarecrow` BIGINT(255) NOT NULL DEFAULT '0' AFTER scientistnpcnew"), sqlConnection);
}
if (turret) {
sqlLibrary.Insert(Sql.Builder.Append($"ALTER TABLE KillRecords ADD COLUMN `turret` BIGINT(255) NOT NULL DEFAULT '0' AFTER heli"), sqlConnection);
}
}
);
}
catch (MySqlException e) {
PrintError("Failed to Update Table (" + e.Message + ")");
}
}
//SQL Player Create/Update
private void CreatePlayerDataSQL(BasePlayer player) {
if (player == null || !player.userID.Get().IsSteamId()) return;
Record record = GetRecord(player);
sqlLibrary.Insert(Sql.Builder.Append($"INSERT KillRecords (steamid, displayname, chicken, boar, stag, wolf, bear, polarbear, shark, horse, fish, scientistnpcnew, scarecrow, dweller, baseplayer, basecorpse, npcplayercorpse, zombie, deaths, suicides, lootcontainer, bradhelicrate, hackablecrate, bradley, heli, turret, underwaterlootcontainer, killchat, treescut, oremined, cactuscut, woodpickup, orepickup, berriespickup, pumpkinpickup, potatopickup, cornpickup, mushroompickup, hemppickup, seedpickup) " + $"VALUES ('" + $"{record.id}', " + $"'{RemoveSpecialCharacters(record.displayname)}', " + $"'{record.chicken}', " + $"'{record.boar}', " + $"'{record.stag}', " + $"'{record.wolf}', " + $"'{record.bear}', " + $"'{record.polarbear}', " + $"'{record.shark}', " + $"'{record.horse}', " + $"'{record.fish}', " + $"'{record.scientistnpcnew}', " + $"'{record.scarecrow}', " + $"'{record.dweller}', " + $"'{record.baseplayer}', " + $"'{record.basecorpse}', " + $"'{record.npcplayercorpse}', " + $"'{record.zombie}', " + $"'{record.deaths}', " + $"'{record.suicides}', " + $"'{record.lootcontainer}', " + $"'{record.bradhelicrate}', " + $"'{record.hackablecrate}', " + $"'{record.bradley}', " + $"'{record.heli}', " + $"'{record.turret}', " + $"'{record.underwaterlootcontainer}', " + $"'{record.killchat}', " + $"'{record.treescut}', " + $"'{record.oremined}', " + $"'{record.cactuscut}', " + $"'{record.woodpickup}', " + $"'{record.orepickup}', " + $"'{record.berriespickup}', " + $"'{record.pumpkinpickup}', " + $"'{record.potatopickup}', " + $"'{record.cornpickup}', " + $"'{record.mushroompickup}', " + $"'{record.hemppickup}', " + $"'{record.seedpickup}'" + $");"), sqlConnection);
}
private void UpdatePlayersSQL() {
bool newplayer = false;
sqlLibrary.Query(Sql.Builder.Append($"SELECT steamid FROM KillRecords"), sqlConnection, list => {
if (list.IsEmpty()) {
newplayer = true;
}
if (newplayer) {
foreach (var r in _recordCache) {
if (!r.Key.IsSteamId()) continue;
sqlLibrary.Insert(Sql.Builder.Append($"INSERT KillRecords (steamid, displayname, chicken, boar, stag, wolf, bear, polarbear, shark, horse, fish, scientistnpcnew, scarecrow, dweller, baseplayer, basecorpse, npcplayercorpse, zombie, deaths, suicides, lootcontainer, bradhelicrate, hackablecrate, bradley, heli, turret, underwaterlootcontainer, killchat, treescut, oremined, cactuscut, woodpickup, orepickup, berriespickup, pumpkinpickup, potatopickup, cornpickup, mushroompickup, hemppickup, seedpickup) " + $"VALUES ('" + $"{r.Value.id}', " + $"'{RemoveSpecialCharacters(r.Value.displayname)}', " + $"'{r.Value.chicken}', " + $"'{r.Value.boar}', " + $"'{r.Value.stag}', " + $"'{r.Value.wolf}', " + $"'{r.Value.bear}', " + $"'{r.Value.polarbear}', " + $"'{r.Value.shark}', " + $"'{r.Value.horse}', " + $"'{r.Value.fish}', " + $"'{r.Value.scientistnpcnew}', " + $"'{r.Value.scarecrow}', " + $"'{r.Value.dweller}', " + $"'{r.Value.baseplayer}', " + $"'{r.Value.basecorpse}', " + $"'{r.Value.npcplayercorpse}', " + $"'{r.Value.zombie}', " + $"'{r.Value.deaths}', " + $"'{r.Value.suicides}', " + $"'{r.Value.lootcontainer}', " + $"'{r.Value.bradhelicrate}', " + $"'{r.Value.hackablecrate}', " + $"'{r.Value.bradley}', " + $"'{r.Value.heli}', " + $"'{r.Value.turret}', " + $"'{r.Value.underwaterlootcontainer}', " + $"'{r.Value.killchat}', " + $"'{r.Value.treescut}', " + $"'{r.Value.oremined}', " + $"'{r.Value.cactuscut}', " + $"'{r.Value.woodpickup}', " + $"'{r.Value.orepickup}', " + $"'{r.Value.berriespickup}', " + $"'{r.Value.pumpkinpickup}', " + $"'{r.Value.potatopickup}', " + $"'{r.Value.cornpickup}', " + $"'{r.Value.mushroompickup}', " + $"'{r.Value.hemppickup}', " + $"'{r.Value.seedpickup}' " + $");"), sqlConnection);
}
}
}
);
sqlLibrary.Query(Sql.Builder.Append($"SELECT steamid FROM KillRecords"), sqlConnection, list => {
foreach (var entry in list) {
foreach (var r in _recordCache) {
if (!r.Key.IsSteamId()) continue;
if (r.Key == entry["steamid"].ToString()) {
sqlLibrary.Update(Sql.Builder.Append($"UPDATE KillRecords SET " + $"steamid='{r.Value.id}', " + $"displayname='{RemoveSpecialCharacters(r.Value.displayname)}', " + $"chicken='{r.Value.chicken}', " + $"boar='{r.Value.boar}', " + $"stag='{r.Value.stag}', " + $"wolf='{r.Value.wolf}', " + $"bear='{r.Value.bear}', " + $"polarbear='{r.Value.polarbear}', " + $"shark='{r.Value.shark}', " + $"horse='{r.Value.horse}', " + $"fish='{r.Value.fish}', " + $"scientistnpcnew='{r.Value.scientistnpcnew}', " + $"scarecrow='{r.Value.scarecrow}', " + $"dweller='{r.Value.dweller}', " + $"baseplayer='{r.Value.baseplayer}', " + $"basecorpse='{r.Value.basecorpse}', " + $"npcplayercorpse='{r.Value.npcplayercorpse}', " + $"zombie='{r.Value.zombie}', " + $"deaths='{r.Value.deaths}', " + $"suicides='{r.Value.suicides}', " + $"lootcontainer='{r.Value.lootcontainer}', " + $"bradhelicrate='{r.Value.bradhelicrate}', " + $"hackablecrate='{r.Value.hackablecrate}', " + $"bradley='{r.Value.bradley}', " + $"heli='{r.Value.heli}', " + $"turret='{r.Value.turret}', " + $"underwaterlootcontainer='{r.Value.underwaterlootcontainer}', " + $"killchat='{r.Value.killchat}', " + $"treescut='{r.Value.treescut}', " + $"oremined='{r.Value.oremined}', " + $"cactuscut='{r.Value.cactuscut}', " + $"woodpickup='{r.Value.woodpickup}', " + $"orepickup='{r.Value.orepickup}', " + $"berriespickup='{r.Value.berriespickup}', " + $"pumpkinpickup='{r.Value.pumpkinpickup}', " + $"potatopickup='{r.Value.potatopickup}', " + $"cornpickup='{r.Value.cornpickup}', " + $"mushroompickup='{r.Value.mushroompickup}', " + $"hemppickup='{r.Value.hemppickup}', " + $"seedpickup='{r.Value.seedpickup}' " + $"WHERE steamid = '{r.Key}';"), sqlConnection);
}
}
}
}
);
}
private void UpdatePlayersDataSQL() {
foreach (var r in _recordCache) {
if (!r.Key.IsSteamId()) continue;
sqlLibrary.Update(Sql.Builder.Append($"UPDATE KillRecords SET " + $"steamid='{r.Value.id}', " + $"displayname='{RemoveSpecialCharacters(r.Value.displayname)}', " + $"chicken='{r.Value.chicken}', " + $"boar='{r.Value.boar}', " + $"stag='{r.Value.stag}', " + $"wolf='{r.Value.wolf}', " + $"bear='{r.Value.bear}', " + $"polarbear='{r.Value.polarbear}', " + $"shark='{r.Value.shark}', " + $"horse='{r.Value.horse}', " + $"fish='{r.Value.fish}', " + $"scientistnpcnew='{r.Value.scientistnpcnew}', " + $"scarecrow='{r.Value.scarecrow}', " + $"dweller='{r.Value.dweller}', " + $"baseplayer='{r.Value.baseplayer}', " + $"basecorpse='{r.Value.basecorpse}', " + $"npcplayercorpse='{r.Value.npcplayercorpse}', " + $"zombie='{r.Value.zombie}', " + $"deaths='{r.Value.deaths}', " + $"suicides='{r.Value.suicides}', " + $"lootcontainer='{r.Value.lootcontainer}', " + $"bradhelicrate='{r.Value.bradhelicrate}', " + $"hackablecrate='{r.Value.hackablecrate}', " + $"bradley='{r.Value.bradley}', " + $"heli='{r.Value.heli}', " + $"turret='{r.Value.turret}', " + $"underwaterlootcontainer='{r.Value.underwaterlootcontainer}', " + $"killchat='{r.Value.killchat}', " + $"treescut='{r.Value.treescut}', " + $"oremined='{r.Value.oremined}', " + $"cactuscut='{r.Value.cactuscut}', " + $"woodpickup='{r.Value.woodpickup}', " + $"orepickup='{r.Value.orepickup}', " + $"berriespickup='{r.Value.berriespickup}', " + $"pumpkinpickup='{r.Value.pumpkinpickup}', " + $"potatopickup='{r.Value.potatopickup}', " + $"cornpickup='{r.Value.cornpickup}', " + $"mushroompickup='{r.Value.mushroompickup}', " + $"hemppickup='{r.Value.hemppickup}', " + $"seedpickup='{r.Value.seedpickup}' " + $"WHERE steamid = '{r.Key}';"), sqlConnection);
}
}
private void UpdatePlayerDataSQL(BasePlayer player) {
if (player == null || !player.userID.Get().IsSteamId()) return;
Record record = GetRecord(player);
sqlLibrary.Update(Sql.Builder.Append($"UPDATE KillRecords SET " + $"steamid='{record.id}', " + $"displayname='{RemoveSpecialCharacters(player.displayName)}', " + $"chicken='{record.chicken}', " + $"boar='{record.boar}', " + $"stag='{record.stag}', " + $"wolf='{record.wolf}', " + $"bear='{record.bear}', " + $"polarbear='{record.polarbear}', " + $"shark='{record.shark}', " + $"horse='{record.horse}', " + $"fish='{record.fish}', " + $"scientistnpcnew='{record.scientistnpcnew}', " + $"scarecrow='{record.scarecrow}', " + $"dweller='{record.dweller}', " + $"baseplayer='{record.baseplayer}', " + $"basecorpse='{record.basecorpse}', " + $"npcplayercorpse='{record.npcplayercorpse}', " + $"zombie='{record.zombie}', " + $"deaths='{record.deaths}', " + $"suicides='{record.suicides}', " + $"lootcontainer='{record.lootcontainer}', " + $"bradhelicrate='{record.bradhelicrate}', " + $"hackablecrate='{record.hackablecrate}', " + $"bradley='{record.bradley}', " + $"heli='{record.heli}', " + $"turret='{record.turret}', " + $"underwaterlootcontainer='{record.underwaterlootcontainer}', " + $"killchat='{record.killchat}', " + $"treescut='{record.treescut}', " + $"oremined='{record.oremined}', " + $"cactuscut='{record.cactuscut}', " + $"woodpickup='{record.woodpickup}', " + $"orepickup='{record.orepickup}', " + $"berriespickup='{record.berriespickup}', " + $"pumpkinpickup='{record.pumpkinpickup}', " + $"potatopickup='{record.potatopickup}', " + $"cornpickup='{record.cornpickup}', " + $"mushroompickup='{record.mushroompickup}', " + $"hemppickup='{record.hemppickup}', " + $"seedpickup='{record.seedpickup}' " + $"WHERE steamid = '{player.UserIDString}';"), sqlConnection);
}
private void CheckPlayerDataSQL(BasePlayer player) {
if (player == null || !player.userID.Get().IsSteamId()) return;
bool newplayer = true;
sqlLibrary.Query(Sql.Builder.Append($"SELECT steamid FROM KillRecords"), sqlConnection, list => {
foreach (var entry in list) {
if (entry["steamid"].ToString() == player.UserIDString) {
UpdatePlayerDataSQL(player);
newplayer = false;
}
}
if (newplayer) {
CreatePlayerDataSQL(player);
}
}
);
}
//SQL Load Data
private void LoadSQL() {
sqlLibrary.Query(Sql.Builder.Append($"SELECT * FROM KillRecords"), sqlConnection, list => {
foreach (var tsqlplayer in list) {
Record record;
if (!_recordCache.TryGetValue(tsqlplayer["steamid"].ToString(), out record)) {
_recordCache[tsqlplayer["steamid"].ToString()] = record = new Record {
chicken = Convert.ToInt32(tsqlplayer["chicken"]), boar = Convert.ToInt32(tsqlplayer["boar"]), stag = Convert.ToInt32(tsqlplayer["stag"]), wolf = Convert.ToInt32(tsqlplayer["wolf"]), bear = Convert.ToInt32(tsqlplayer["bear"]), shark = Convert.ToInt32(tsqlplayer["shark"]), horse = Convert.ToInt32(tsqlplayer["horse"]), fish = Convert.ToInt32(tsqlplayer["fish"]), scientistnpcnew = Convert.ToInt32(tsqlplayer["scientistnpcnew"]), dweller = Convert.ToInt32(tsqlplayer["dweller"]), baseplayer = Convert.ToInt32(tsqlplayer["baseplayer"]), basecorpse = Convert.ToInt32(tsqlplayer["basecorpse"]), npcplayercorpse = Convert.ToInt32(tsqlplayer["npcplayercorpse"]), zombie = Convert.ToInt32(tsqlplayer["zombie"]), deaths = Convert.ToInt32(tsqlplayer["deaths"]), suicides = Convert.ToInt32(tsqlplayer["suicides"]), lootcontainer = Convert.ToInt32(tsqlplayer["lootcontainer"]), bradhelicrate = Convert.ToInt32(tsqlplayer["bradhelicrate"]), hackablecrate = Convert.ToInt32(tsqlplayer["hackablecrate"]), bradley = Convert.ToInt32(tsqlplayer["bradley"]), heli = Convert.ToInt32(tsqlplayer["heli"]), underwaterlootcontainer = Convert.ToInt32(tsqlplayer["underwaterlootcontainer"]), killchat = Convert.ToBoolean(tsqlplayer["killchat"]), treescut = Convert.ToInt32(tsqlplayer["treescut"]), oremined = Convert.ToInt32(tsqlplayer["oremined"]), cactuscut = Convert.ToInt32(tsqlplayer["cactuscut"]), woodpickup = Convert.ToInt32(tsqlplayer["woodpickup"]), orepickup = Convert.ToInt32(tsqlplayer["orepickup"]), berriespickup = Convert.ToInt32(tsqlplayer["berriespickup"]), pumpkinpickup = Convert.ToInt32(tsqlplayer["pumpkinpickup"]), potatopickup = Convert.ToInt32(tsqlplayer["potatopickup"]), cornpickup = Convert.ToInt32(tsqlplayer["cornpickup"]), mushroompickup = Convert.ToInt32(tsqlplayer["mushroompickup"]), hemppickup = Convert.ToInt32(tsqlplayer["hemppickup"]), seedpickup = Convert.ToInt32(tsqlplayer["seedpickup"])
}
;
record.id = tsqlplayer["steamid"].ToString();
record.displayname = tsqlplayer["displayname"].ToString();
}
}
}
);
}
//SQL Delete Data
private void DeleteSQL() {
sqlLibrary.Delete(Sql.Builder.Append($"DELETE FROM KillRecords;"), sqlConnection);
}
#endregion
#region Load/Save
private void Init() {
_recordCache = new Dictionary<string, Record>();
_dataCache = new Dictionary<ulong, Data>();
_heliCache = new Dictionary<ulong, Heli>();
}
private void OnServerInitialized() {
cmd.AddChatCommand(config.playerChatCommands.krhelp, this, KRHelp);
cmd.AddChatCommand(config.playerChatCommands.pkills, this, PKills);
cmd.AddChatCommand(config.playerChatCommands.pkillschat, this, PKillsChat);
cmd.AddChatCommand(config.playerChatCommands.topkills, this, TopKills);
cmd.AddChatCommand(config.playerChatCommands.topkillschat, this, TopKillsChat);
cmd.AddChatCommand(config.playerChatCommands.totalkills, this, TotalKills);
cmd.AddChatCommand(config.playerChatCommands.totalkillschat, this, TotalKillsChat);
cmd.AddChatCommand(config.playerChatCommands.leadkills, this, LeadKills);
cmd.AddChatCommand(config.playerChatCommands.pstats, this, PStats);
cmd.AddChatCommand(config.playerChatCommands.pstatschat, this, PStatsChat);
cmd.AddChatCommand(config.playerChatCommands.topstats, this, TopStats);
cmd.AddChatCommand(config.playerCha
// ... [Code preview truncated due to length. Full source in attached file] ...