using System; using System.Collections.Generic; using System.Linq; using Newtonsoft.Json; using Oxide.Core; using Oxide.Core.Libraries; namespace Oxide.Plugins { [Info("MerricLink", "Merric Gaming", "0.1.0")] [Description("Votes, rewards and player stats for Merric Gaming")] public class MerricLink : RustPlugin { private class Settings { public string ApiUrl = "https://merric-gaming.co.uk/api/plugin/v1"; public string ApiKey = ""; // Your own console commands. Merric only says who voted, it never sends commands public List RewardCommands = new List { "inventory.giveto {id} scrap 100" }; // Paid rewards, by the tier name shown on your server's Merric dashboard public Dictionary> TierCommands = new Dictionary>(); } private class Tally { public int PlaytimeMinutes; public int Kills; public int Deaths; } private class Reward { [JsonProperty("id")] public string Id; [JsonProperty("externalId")] public string ExternalId; [JsonProperty("tier")] public string Tier; } private class RewardList { [JsonProperty("rewards")] public List Rewards; } private class CodeReply { [JsonProperty("code")] public string Code; } private Settings settings; private readonly Dictionary tallies = new Dictionary(); protected override void LoadDefaultConfig() => Config.WriteObject(new Settings(), true); private void Init() { settings = Config.ReadObject(); if (string.IsNullOrEmpty(settings.ApiKey)) PrintWarning("Set ApiKey in oxide/config/MerricLink.json"); } private void OnServerInitialized() { timer.Every(60f, () => { foreach (var p in BasePlayer.activePlayerList) Get(p.UserIDString).PlaytimeMinutes++; DeliverRewards(); }); timer.Every(300f, SendStats); } private void Unload() => SendStats(); private Tally Get(string id) { Tally t; if (!tallies.TryGetValue(id, out t)) tallies[id] = t = new Tally(); return t; } private void OnPlayerDeath(BasePlayer victim, HitInfo info) { if (victim == null || victim.IsNpc || !victim.userID.IsSteamId()) return; Get(victim.UserIDString).Deaths++; var killer = info?.InitiatorPlayer; if (killer != null && killer != victim && !killer.IsNpc) Get(killer.UserIDString).Kills++; } [ChatCommand("merric")] private void MerricCommand(BasePlayer player, string command, string[] args) { if (args.Length == 0 || args[0] != "link") { SendReply(player, "Use /merric link"); return; } var body = JsonConvert.SerializeObject(new { id = player.UserIDString, name = player.displayName }); Call("/link", body, RequestMethod.POST, (code, text) => { if (code != 200) { SendReply(player, "Couldn't get a code. Try again shortly."); return; } SendReply(player, $"Your code is {JsonConvert.DeserializeObject(text).Code}. Enter it at merric-gaming.co.uk/settings/links"); }); } private void SendStats() { if (tallies.Count == 0) return; var players = tallies.Take(200).Select(t => new { id = t.Key, playtimeMinutes = Math.Min(t.Value.PlaytimeMinutes, 60), kills = Math.Min(t.Value.Kills, 500), deaths = Math.Min(t.Value.Deaths, 500), }).ToList(); foreach (var p in players) tallies.Remove(p.id); Call("/stats", JsonConvert.SerializeObject(new { batchId = Guid.NewGuid().ToString("N"), players }), RequestMethod.POST, (code, text) => { if (code != 200) PrintWarning($"Stats weren't saved ({code})"); }); } private void DeliverRewards() { Call("/rewards", null, RequestMethod.GET, (code, text) => { if (code != 200) return; var delivered = new List(); foreach (var r in JsonConvert.DeserializeObject(text).Rewards) { var player = BasePlayer.Find(r.ExternalId); if (player == null || !player.IsConnected) continue; List commands = settings.RewardCommands; if (r.Tier != null && !settings.TierCommands.TryGetValue(r.Tier, out commands)) { PrintWarning($"Add {r.Tier} to TierCommands"); continue; } foreach (var c in commands) rust.RunServerCommand(c.Replace("{id}", player.UserIDString).Replace("{player}", player.displayName)); SendReply(player, "Thanks for supporting this server on Merric!"); delivered.Add(r.Id); } if (delivered.Count > 0) Call("/rewards", JsonConvert.SerializeObject(new { ids = delivered }), RequestMethod.POST, (c, t) => { }); }); } private void Call(string path, string body, RequestMethod method, Action done) { var headers = new Dictionary { ["Authorization"] = "Bearer " + settings.ApiKey, ["Content-Type"] = "application/json" }; webrequest.Enqueue(settings.ApiUrl + path, body, done, this, method, headers, 10f); } } }