Иконка ресурса

FREE AntiNoobRaid : 1.8.5 1.8.5

Нет прав для скачивания
C#:
using Oxide.Core;
using System;
using System.Collections.Generic;
using Oxide.Core.Plugins;
using Oxide.Core.Libraries.Covalence;
using Rust;
using UnityEngine;
using Newtonsoft.Json;
using System.Linq;
namespace Oxide.Plugins {
    [Info("AntiNoobRaid", "Slydelix", "1.8.5", ResourceId = 2697)]
    class AntiNoobRaid : RustPlugin {
        [PluginReference]
        private Plugin PlaytimeTracker, WipeProtection, GameTipAPI, Clans;
        //set this to true if you are having issues with the plugin
        private bool debug = false;
        private List<BasePlayer> cooldown = new List<BasePlayer>();
        private List<BasePlayer> MessageCooldown = new List<BasePlayer>();
        //private Dictionary<ulong, Timer> RaidTimerDictionary = new Dictionary<ulong, Timer>();
        private Dictionary<string, string> raidtools = new Dictionary<string, string> {
            {
                "ammo.rocket.fire", "rocket_fire"
            }
            , {
                "ammo.rocket.hv", "rocket_hv"
            }
            , {
                "ammo.rocket.basic", "rocket_basic"
            }
            , {
                "explosive.timed", "explosive.timed.deployed"
            }
            , {
                "surveycharge", "survey_charge.deployed"
            }
            , {
                "explosive.satchel", "explosive.satchel.deployed"
            }
            , {
                "grenade.beancan", "grenade.beancan.deployed"
            }
            , {
                "grenade.f1", "grenade.f1.deployed"
            }
        }
        ;
        private int layers = LayerMask.GetMask("Construction", "Deployed");
        private readonly string AdminPerm = "antinoobraid.admin";
        private readonly string NoobPerm = "antinoobraid.noob";
#region Config
        private class ConfigFile {
            [JsonProperty("Allow clan members to destroy each others entities")]
            public bool CheckClanForOwner;
            [JsonProperty("Allow twig to be destroyed even when owner is noob")]
            public bool AllowTwigDestruction;
            [JsonProperty("Check full ownership of the base instead of only one block")]
            public bool CheckFullOwnership;
            [JsonProperty("Check Steam for in game time")]
            public bool CheckSteam;
            [JsonProperty("Days of inactivity after which player will be raidable")]
            public double InactivityRemove;
            [JsonProperty("Ignore twig when calculating base ownership (prevents exploiting)")]
            public bool IgnoreTwig;
            [JsonProperty("In-game steam time which mark player as non-noob (hours)")]
            public double SteamInGameTime;
            [JsonProperty("Kill fireballs when someone tries to raid protected player with fire (prevents lag)")]
            public bool KillFire;
            [JsonProperty("List of entities that can be destroyed even if owner is a noob, true = destroyable everywhere (not inside of owners TC range)")]
            public Dictionary<string, bool> AllowedEntities = PlaceHolderDictionary;
            [JsonProperty("Manual Mode")]
            public bool ManualMode;
            [JsonProperty("Notify player on first connection with protection time")]
            public bool MessageOnFirstConnection;
            [JsonProperty("Prevent new players from raiding")]
            public bool PreventNew;
            [JsonProperty("Refund explosives")]
            public bool Refund;
            [JsonProperty("Refunds before player starts losing explosives")]
            public int RefundTimes;
            [JsonProperty("Remove noob status of a raider on raid attempt")]
            public bool UnNoobNew;
            [JsonProperty("Remove noob status of a raider who is manually marked as a noob on raid attempt")]
            public bool UnNoobManual;
            [JsonProperty("Remove protection from all clan members when a member tries to raid")]
            public bool RemoveClanProtection;
            [JsonProperty("Show message for not being able to raid")]
            public bool ShowMessage;
            [JsonProperty("Show time until raidable")]
            public bool ShowTime;
            [JsonProperty("Steam API key")]
            public string ApiKey;
            [JsonProperty("Time (seconds) after which noob will lose protection (in-game time)")]
            public int ProtectionTime;
            [JsonProperty("Use game tips to send first connection message to players")]
            public bool UseGT;
            [JsonProperty("User data refresh interval (seconds)")]
            public int Frequency;
            [JsonProperty("Allow team members to destroy each others entities")]
            public bool CheckTeamForOwner;
            [JsonProperty("Remove protection from all team members when a member tries to raid")]
            public bool RemoveTeamProtection;
            //[JsonProperty("Automatically add raid protection to user after raid")]
            //public bool AutoAddProtection;
            //[JsonProperty("Time (minutes) after which the raided person gains raid protection")]
            //public int AutoMinutes;
            public static Dictionary<string, bool> PlaceHolderDictionary = new Dictionary<string, bool> {
                {
                    "Placeholder1", true
                }
                , {
                    "Placeholder2", true
                }
                , {
                    "Placeholder3", true
                }
                , {
                    "Placeholder4", true
                }
                , {
                    "Placeholder5", true
                }
                ,
            }
            ;
            public static readonly ConfigFile DefaultConfigFile = new ConfigFile {
                UnNoobManual = true, ProtectionTime = 21600, SteamInGameTime = 200, Frequency = 30, RefundTimes = 1, InactivityRemove = 7, ApiKey = string.Empty, CheckFullOwnership = true, CheckSteam = true, CheckClanForOwner = true, RemoveClanProtection = false, Refund = true, IgnoreTwig = true, KillFire = true, ManualMode = false, MessageOnFirstConnection = true, UseGT = true, AllowTwigDestruction = true, ShowMessage = true, ShowTime = false, PreventNew = true, UnNoobNew = true, AllowedEntities = PlaceHolderDictionary, CheckTeamForOwner = true, RemoveTeamProtection = true,  //AutoAddProtection = true,
                //AutoMinutes = 60
            }
            ;
        }
        private ConfigFile config;
        protected override void LoadDefaultConfig() {
            Config.Clear();
            PrintWarning("Creating new config file");
            Config.WriteObject(ConfigFile.DefaultConfigFile, true);
            SaveConfig();
        }
#endregion
#region Lang
        protected override void LoadDefaultMessages() {
            lang.RegisterMessages(new Dictionary<string, string>() {
                {
                    "NoPlayerFound", "Couldn't find '{0}'"
                }
                , {
                    "NotNumber", "{0} is not a number"
                }
                , {
                    "antinoobcmd_syntax", "Wrong syntax! /antinoob <addnoob|checksteam|removenoob|wipe>"
                }
                , {
                    "antinoobcmd_addnoob_syntax", "Wrong syntax! /antinoob addnoob <name/steamid>"
                }
                , {
                    "antinoobcmd_alreadynoob", "{0} is already marked as a noob"
                }
                , {
                    "antinoobcmd_marked", "Marked {0} as a noob"
                }
                , {
                    "antinoobcmd_removenoob_syntax", "Wrong syntax! /antinoob removenoob <name/steamid>"
                }
                , {
                    "antinoobcmd_removednoob", "{0} does not have a noob status anymore"
                }
                , {
                    "antinoobcmd_missingnoob", "{0} is not a noob"
                }
                , {
                    "antinoobcmd_wipe_syntax", "Missing argument! <all|playerdata|attempts>"
                }
                , {
                    "dataFileWiped", "Data file successfully wiped"
                }
                , {
                    "dataFileWiped_attempts", "Data file successfully wiped (raid attempts)"
                }
                , {
                    "dataFileWiped_playerdata", "Data file successfully wiped (player data)"
                }
                , {
                    "struct_noowner", "Structure at {0} has no owner!"
                }
                , {
                    "clan_lostnoob" , "Clan '{0}' lost their noob status because they tried to raid"
                }
                , {
                    "new_user_lostprotection" , "You lost your noob protection for damaging a structure"
                }
                , {
                    "console_lostnoobstatus", "{0} hasn't connected for {1} days so he lost his noob status (can be raided)"
                }
                , {
                    "console_notenough", "{0} doesn't have enough hours in game to be marked as a non-noob"
                }
                , {
                    "rn_manual", "This will remove your noob status, type /removenoob 'yes' to confirm."
                }
                , {
                    "rn_success", "Successfully removed your noob status"
                }
                , {
                    "firstconnectionmessage", "You are a new player so your buildings are protected for first {0} hours of your time on server"
                }
                , {
                    "steam_checkstart", "{0} connected, checking Steam"
                }
                , {
                    "steam_marking", "Marking {0} as non noob"
                }
                , {
                    "steam_connected", "{0} has connected with {1} in game hours"
                }
                , {
                    "steam_private", "Steam profile of {0} is private"
                }
                , {
                    "steam_responsewrong", "Failed to contact steam API, profile is private/wrong API key"
                }
                , {
                    "steam_wrongapikey", "Invalid API key"
                }
                , {
                    "pt_notInstalled_first", "Playtime Tracker is not installed, will check again in 30 seconds"
                }
                , {
                    "pt_notInstalled", "Playtime Tracker is not installed!"
                }
                , {
                    "pt_detected", "Playtime Tracker detected"
                }
                , {
                    "userinfo_nofound", "Failed to get playtime info for {0}! trying again in 20 seconds!"
                }
                , {
                    "can_attack", "This structure is not raid protected"
                }
                , {
                    "NotLooking", "You are not looking at a building/deployable"
                }
                , {
                    "refunditem_help", "Wrong Syntax! /refunditem add <you have to hold the item you want to add>\n/refunditem remove <you have to hold the item you want to remove>\n/refunditem list\n/refunditem clear\n/refunditem all <sets all raid tools as refundable>"
                }
                , {
                    "refunditem_needholditem", "You need to hold the item you want to add/remove from refund list"
                }
                , {
                    "refunditem_notexplosive", "This item is not an explosive"
                }
                , {
                    "refunditem_added", "Added '{0}' to list of items to refund"
                }
                , {
                    "refunditem_alreadyonlist", "This item is already on the list"
                }
                , {
                    "refunditem_notonlist", "This item is not on the list"
                }
                , {
                    "refunditem_removed", "Removed '{0}' from the list of items to refund"
                }
                , {
                    "refunditem_addedall", "Added all raid tools to refund list"
                }
                , {
                    "refunditem_cleared", "Cleared list of items to refund"
                }
                , {
                    "refunditem_empty", "There are no item set up yet"
                }
                , {
                    "refunditem_list", "List of items which will get refunded: \n{0}"
                }
                , {
                    "refund_free", "Your '{0}' was refunded."
                }
                , {
                    "refund_last", "Your '{0}' was refunded but will not be next time."
                }
                , {
                    "refund_1time", "Your '{0}' was refunded.After 1 more attempt it wont be refunded."
                }
                , {
                    "refund_nTimes", "Your '{0}' was refunded.After {1} more attempts it wont be refunded"
                }
                , {
                    "cannot_attack_no_time", "This entity cannot be destroyed because it was built by a new player"
                }
                , {
                    "cannot_attack_new_raider", "Because you are a new player you cannot raid (yet)"
                }
                , {
                    "cannot_attack_time", "This entity cannot be destroyed because it was built by a new player ({0})"
                }
                , {
                    "secs", " seconds"
                }
                , {
                    "mins", " minutes"
                }
                , {
                    "min", " minute"
                }
                , {
                    "hours", " hours"
                }
                , {
                    "hour", " hour"
                }
                , {
                    "day", " day"
                }
                , {
                    "days", " days"
                }
            }
            , this);
        }
#endregion
#region DataFile/Classes
        private class BuildingInfo {
            public static HashSet<BuildingInfo> buildCache = new HashSet<BuildingInfo>();
            public BuildingInfo() {
            }
            public uint buildingID;
            public ulong OwnerID;
            public DateTime lastUpdate;
            public static BuildingInfo GetByBuildingID(uint bID) {
                foreach (var entry in buildCache) if (entry.buildingID == bID) return entry;
                return null;
            }
            public double GetCacheAge() {
                if (lastUpdate == null) return -1;
                return DateTime.UtcNow.Subtract(lastUpdate).TotalSeconds;
            }
        }
        private class ClanInfo {
            public static HashSet<ClanInfo> clanCache = new HashSet<ClanInfo>();
            public ClanInfo() {
            }
            public static ClanInfo FindClanByName(string clanName) {
                foreach (var clan in ClanInfo.clanCache) if (clan.clanName == clanName) return clan;
                return null;
            }
            public static ClanInfo GetClanOf(ulong ID) {
                foreach (var clan in ClanInfo.clanCache) if (clan.members.Contains(ID)) return clan;
                return null;
            }
            public string clanName {
                get;
                set;
            }
            public List<ulong> members = new List<ulong>();
        }
        private class StoredData {
            public Dictionary<ulong, double> players = new Dictionary<ulong, double>();
            public Dictionary<ulong, int> AttackAttempts = new Dictionary<ulong, int>();
            public Dictionary<string, string> ItemList = new Dictionary<string, string>();
            public List<ulong> playersWithNoData = new List<ulong>();
            public List<ulong> FirstMessaged = new List<ulong>();
            public Dictionary<ulong, string> lastConnection = new Dictionary<ulong, string>();
            public List<ulong> IgnoredPlayers = new List<ulong>();
            public StoredData() {
            }
        }
        private void SaveData() => Interface.Oxide.DataFileSystem.WriteObject(this.Name, storedData);
        StoredData storedData;
#endregion
#region Steam
        private class SteamGames {
            public Content response;
            public class Content {
                public int game_count;
                public Game[] games;
                public class Game {
                    public uint appid;
                    public int playtime_2weeks;
                    public int playtime_forever;
                }
            }
        }
#endregion
#region Hooks
        private void Init() {
            permission.RegisterPermission(AdminPerm, this);
            permission.RegisterPermission(NoobPerm, this);
            storedData = Interface.Oxide.DataFileSystem.ReadObject<StoredData>(this.Name);
            config = Config.ReadObject<ConfigFile>();
            NextTick(() => Config.WriteObject(config));
            //if (config.AutoMinutes <= 0 && config.AutoAddProtection) PrintError("Time (minutes) after which the raided person gains raid protection is set to 0!!! Change this!!");
        }
        private void RegisterCommands() {
            foreach (var command in AdminCommands) AddCovalenceCommand(command.Key, command.Value, AdminPerm);
        }
        private void Loaded() {
            RegisterCommands();
            foreach (var entry in storedData.players.Where(x => !storedData.lastConnection.ContainsKey(x.Key))) storedData.lastConnection.Add(entry.Key, string.Empty);
            if (!config.ManualMode) {
                StartChecking();
                CheckPlayersWithNoInfo();
            }
            timer.Every(60f, RefreshClanCache);
            if (config.ManualMode) foreach (var p in BasePlayer.activePlayerList.Where(x => !storedData.players.ContainsKey(x.userID))) storedData.players.Add(p.userID, -50d);
            if (PlaytimeTracker == null) {
                PrintWarning(lang.GetMessage("pt_notInstalled_first", this, null));
                timer.Once(30f, () => {
                    if (PlaytimeTracker == null) {
                        PrintWarning(lang.GetMessage("pt_notInstalled", this, null));
                        return;
                    }
                    PrintWarning(lang.GetMessage("pt_detected", this, null));
                }
                );
            }
        }
        private object OnEntityTakeDamage(BaseCombatEntity entity, HitInfo hitinfo) {
            if (hitinfo == null || entity == null) return null;
            var dmgType = hitinfo?.damageTypes?.GetMajorityDamageType() ?? DamageType.Generic;
            if (dmgType == DamageType.Decay || dmgType == DamageType.Generic) return null;
            if (!(entity is BuildingBlock || entity is Door || entity.OwnerID != 0u || entity.PrefabName.Contains("deployable"))) return null;
            if (config.AllowTwigDestruction && ((entity as BuildingBlock)?.grade == BuildingGrade.Enum.Twigs)) return null;
            if (config.AllowedEntities.ContainsKey(entity.ShortPrefabName)) {
                if (config.AllowedEntities[entity.ShortPrefabName] || entity.GetBuildingPrivilege() == null) return null;
                if (!entity.GetBuildingPrivilege().authorizedPlayers.Select(x => x.userid).Contains(entity.OwnerID)) return null;
            }
            BasePlayer attacker = hitinfo.InitiatorPlayer;
            if (attacker == null || entity?.OwnerID == attacker?.userID) return null;
            if (storedData.IgnoredPlayers.Contains(attacker.userID)) return null;
            var owner = config.CheckFullOwnership ? FullOwner(entity) : entity.OwnerID;
            if (owner == 0u) return null;
            if (owner == attacker?.userID) return null;
            //No good
            /*if (config.AutoAddProtection)
            {
                if (RaidTimerDictionary.ContainsKey(owner))
                {
                    RaidTimerDictionary[owner]?.Destroy();
                    if (RaidTimerDictionary.ContainsKey(owner)) RaidTimerDictionary.Remove(owner);

                    RaidTimerDictionary.Add(owner, timer.Once(60f * config.AutoMinutes, () => {
                        storedData.players[owner] = -25d;
                        if (RaidTimerDictionary.ContainsKey(owner)) RaidTimerDictionary.Remove(owner);
                    }));
                }  

                else RaidTimerDictionary.Add(owner, timer.Once(60f * config.AutoMinutes, () => {
                    storedData.players[owner] = -25d;
                    if (RaidTimerDictionary.ContainsKey(owner)) RaidTimerDictionary.Remove(owner);
                }));
            }*/
            if (config.CheckClanForOwner) {
                ulong userID = attacker?.userID ?? 0u;
                var clan = ClanInfo.GetClanOf(userID) ?? null;
                if (clan == null) {
                    var clanName = Clans?.Call<string>("GetClanOf", userID) ?? string.Empty;
                    if (!string.IsNullOrEmpty(clanName)) {
                        var members = GetClanMembers(clanName);
                        var claninfo = new ClanInfo {
                            clanName = clanName, members = members
                        }
                        ;
                        ClanInfo.clanCache.Add(claninfo);
                        if (claninfo.members.Contains(owner)) return null;
                    }
                }
                else if (clan.members.Contains(owner)) return null;
            }
            if (config.CheckTeamForOwner) {
                var instance = RelationshipManager.Instance;
                if (instance == null) PrintWarning("RelationshipManager instance is null! how is this even possible?");
                else {
                    BasePlayer ownerPlayer;
                    if (instance.cachedPlayers.TryGetValue(owner, out ownerPlayer)) {
                        if (ownerPlayer.currentTeam == attacker.currentTeam && ownerPlayer.currentTeam != 0) return null;
                    }
                }
            }
            //I kinda forgot why this check is needed :/
            if (config.RemoveTeamProtection && !string.IsNullOrEmpty(hitinfo?.WeaponPrefab?.ShortPrefabName)) {
                if (attacker.currentTeam != 0) {
                    var team = RelationshipManager.Instance?.teams[attacker.currentTeam];
                    foreach (var member in team.members) storedData.players[member] = -50d;
                }
            }
            if (config.RemoveClanProtection && !string.IsNullOrEmpty(hitinfo?.WeaponPrefab?.ShortPrefabName)) {
                string val;
                if (raidtools.TryGetValue(hitinfo?.WeaponPrefab?.ShortPrefabName, out val)) RemoveClanP(attacker?.userID ?? 0u);
            }
            bool wipe = false;
            try {
                if (WipeProtection != null) wipe = WipeProtection.Call<bool>("WipeProtected");
            }
            catch (Exception e) {
                PrintError("Caught an exception while trying to get data from WipeProtection: " + e.Message);
            }
            if (wipe) return null;
            if (cooldown.Contains(attacker)) {
                RemoveCD(cooldown, attacker);
                if (PlayerIsNew(owner)) {
                    hitinfo.damageTypes = new DamageTypeList();
                    hitinfo.DoHitEffects = false;
                    hitinfo.HitMaterial = 0;
                    return true;
                }
                return null;
            }
            cooldown.Add(attacker);
            RemoveCD(cooldown, attacker);
            LogPlayer(attacker);
            string name = hitinfo?.WeaponPrefab?.ShortPrefabName ?? string.Empty;
            if (config.PreventNew && PlayerIsNew(attacker.userID)) {
                //keep in mind, antinoobraid.noob perm doesn't get removed
                hitinfo.damageTypes = new DamageTypeList();
                hitinfo.DoHitEffects = false;
                hitinfo.HitMaterial = 0;
                NextTick(() => {
                    //if player was *manually* set to noob we don't remove his protection on raid attempt
                    if (config.UnNoobNew) {
                        if (storedData.players[attacker.userID] >= 0 || (storedData.players[attacker.userID] == -25d && config.UnNoobManual)) {
                            storedData.players[attacker.userID] = -50d;
                            SendReply(attacker, lang.GetMessage("new_user_lostprotection", this, attacker.UserIDString));
                        }
                    }
                    else SendReply(attacker, lang.GetMessage("cannot_attack_new_raider", this, attacker.UserIDString));
                    Refund(attacker, name, entity);
                }
                );
                return true;
            }
            if (PlayerIsNew(owner)) {
                hitinfo.damageTypes = new DamageTypeList();
                hitinfo.DoHitEffects = false;
                hitinfo.HitMaterial = 0;
                NextTick(() => {
                    MessagePlayer(attacker, owner);
                    Refund(attacker, name, entity);
                }
                );
                return true;
            }
            return null;
        }
        private void OnFireBallDamage(FireBall fireball, BaseCombatEntity entity, HitInfo hitinfo) {
            if (hitinfo == null || fireball == null || entity == null || !config.KillFire) return;
            if (!(entity is BuildingBlock || entity is Door || entity.OwnerID != 0u || entity.PrefabName.Contains("deployable")) || fireball.IsDestroyed) return;
            if (config.AllowTwigDestruction && ((entity as BuildingBlock)?.grade == BuildingGrade.Enum.Twigs)) return;
            if (config.AllowedEntities.ContainsKey(entity.ShortPrefabName)) {
                if (config.AllowedEntities[entity.ShortPrefabName] || entity.GetBuildingPrivilege() == null) return;
                if (!entity.GetBuildingPrivilege().authorizedPlayers.Select(x => x.userid).Contains(entity.OwnerID)) return;
            }
            BasePlayer attacker = hitinfo?.InitiatorPlayer;
            if (entity?.OwnerID == attacker?.userID) return;
            if (PlayerIsNew(entity.OwnerID)) {
                fireball.Kill();
                var player = fireball.creatorEntity as BasePlayer;
                if (player != null) {
                    if (!MessageCooldown.Contains(player)) {
                        MessagePlayer(player, entity.OwnerID);
                        MessageCooldown.Add(player);
                        RemoveCD(MessageCooldown, player, 1f);
                    }
                }
                return;
            }
        }
        private void OnPlayerDisconnected(BasePlayer player, string reason) => LastConnect(player.userID);
        private void OnServerSave() {
            timer.Once(UnityEngine.Random.Range(5, 15), SaveData);
        }
        private void OnUserConnected(IPlayer player) {
            BasePlayer bp = player.Object as BasePlayer;
            LastConnect(bp.userID);
            if (config.ManualMode) {
                if (!storedData.players.ContainsKey(bp.userID)) {
                    storedData.players.Add(bp.userID, -50d);
                    return;
                }
                if (storedData.players[bp.userID] == -50d || storedData.players[bp.userID] == -25d) return;
                storedData.players[bp.userID] = -50d;
                return;
            }
            SteamCheck(bp.userID, true);
            if (storedData.players.ContainsKey(bp.userID)) if (storedData.players[bp.userID] == -50d || storedData.players[bp.userID] == -25d) return;
            APICall(bp.userID);
            timer.Once(10f, () => FirstMessage(bp));
        }
        private void Unload() {
            SaveData();
        }
#endregion
#region API
        bool IgnorePlayer(object o) {
            ulong id = 0u;
            if (o is BasePlayer) {
                id = (o as BasePlayer).userID;
            }
            else if (ulong.TryParse(o.ToString(), out id)) {
                //Do nothing I guess?
            }
            if (id == 0u) return false;
            if (!storedData.IgnoredPlayers.Contains(id)) {
                storedData.IgnoredPlayers.Add(id);
                SaveData();
                return true;
            }
            return false;
        }
        bool UnIgnorePlayer(object o) {
            ulong id = 0u;
            if (o is BasePlayer) {
                id = (o as BasePlayer).userID;
            }
            else if (ulong.TryParse(o.ToString(), out id)) {
                //Do nothing I guess?
            }
            if (id == 0u) return false;
            if (storedData.IgnoredPlayers.Contains(id)) {
                storedData.IgnoredPlayers.Remove(id);
                SaveData();
                return true;
            }
            return false;
        }
#endregion
#region Methods
        private void RefreshClanCache() {
            foreach (var player in covalence.Players.All.Where(x => !x.IsBanned)) {
                ulong ID = ulong.Parse(player.Id);
                var clanName = Clans?.Call<string>("GetClanOf", ID) ?? string.Empty;
                if (!string.IsNullOrEmpty(clanName)) {
                    if (!ClanInfo.clanCache.Select(x => x.clanName).Contains(clanName)) {
                        var clan = new ClanInfo {
                            clanName = clanName, members = new List<ulong> {
                                ID
                            }
                        }
                        ;
                        ClanInfo.clanCache.Add(clan);
                    }
                    else {
                        foreach (var clan in ClanInfo.clanCache) {
                            if (clanName == clan.clanName && !clan.members.Contains(ID)) clan.members.Add(ID);
                        }
                    }
                }
            }
        }
        private void APICall(ulong ID, bool secondattempt = false) {
            if (PlaytimeTracker == null) {
                Puts(lang.GetMessage("pt_notInstalled", this, null));
                return;
            }
            double apitime = -1;
            try {
                apitime = PlaytimeTracker?.Call<double>("GetPlayTime", ID.ToString()) ?? -1d;
            }
            catch (Exception) {
                Puts(lang.GetMessage("userinfo_nofound", this, null), ID);
                if (!secondattempt) timer.Once(20f, () => APICall(ID, true));
            }
            if (apitime == -1d) {
                if (secondattempt) storedData.playersWithNoData.Add(ID);
                Puts(lang.GetMessage("userinfo_nofound", this, null));
                return;
            }
            if (storedData.playersWithNoData.Contains(ID)) storedData.playersWithNoData.Remove(ID);
            if (storedData.players.ContainsKey(ID)) storedData.players[ID] = apitime;
            else storedData.players.Add(ID, apitime);
        }
        private void Check() {
            if (BasePlayer.activePlayerList.Count == 0) return;
            foreach (BasePlayer bp in BasePlayer.activePlayerList) {
                if (!bp.IsConnected || bp == null) continue;
                if (storedData.playersWithNoData.Contains(bp.userID)) continue;
                var val = 0d;
                if (storedData.players.TryGetValue(bp.userID, out val) && (val == -50d || val == -25d)) continue;
                APICall(bp.userID);
            }
            foreach (BasePlayer bp in BasePlayer.sleepingPlayerList) {
                if (storedData.playersWithNoData.Contains(bp.userID)) continue;
                var val = 0d;
                if (storedData.players.TryGetValue(bp.userID, out val) && (val == -50d || val == -25d)) continue;
                APICall(bp.userID);
            }
        }
        private void Check(ulong ID) {
            if (storedData.playersWithNoData.Contains(ID)) return;
            if (storedData.players[ID] == -50d || storedData.players[ID] == -25d) return;
            APICall(ID);
        }
        private string CheckLeft(int intsecs) {
            var time = DateTime.Now.AddSeconds(intsecs - 1);
            var timespan = time.Subtract(DateTime.Now);
            string t = string.Empty;
            if (timespan.Days != 0) t += timespan.Days + "d ";
            if (timespan.Hours != 0) t += timespan.Hours + "h ";
            if (timespan.Minutes != 0) t += timespan.Minutes + "m ";
            if (timespan.Seconds != 0) t += timespan.Seconds + "s";
            if (t.Last() == ' ') {
                string nw = t.Remove(t.Length - 1);
                return nw;
            }
            return t;
        }
        private void CheckPlayersWithNoInfo() {
            int rate = (config.Frequency <= 10) ? 10 : config.Frequency - 10;
            timer.Every(rate, () => {
                if (storedData.playersWithNoData.Count < 1) return;
                foreach (ulong ID in storedData.playersWithNoData.ToList()) {
                    double time = -1d;
                    try {
                        time = PlaytimeTracker?.Call<double>("GetPlayTime", ID.ToString()) ?? -1d;
                    }
                    catch (Exception) {
                        continue;
                    }
                    if (time == -1d) continue;
                    if (storedData.players.ContainsKey(ID)) {
                        string date = "[" + DateTime.Now.ToString() + "] ";
                        LogToFile(this.Name, date + "Somehow info exists for player that is in data file already (" + ID + ")", this, true);
                        storedData.players[ID] = time;
                        storedData.playersWithNoData.Remove(ID);
                        continue;
                    }
                    storedData.players.Add(ID, time);
                    storedData.playersWithNoData.Remove(ID);
                    continue;
                }
            }
            );
        }
        private void FirstMessage(BasePlayer player) {
            if (!config.MessageOnFirstConnection || storedData.FirstMessaged.Contains(player.userID)) return;
            storedData.FirstMessaged.Add(player.userID);
            var val = 0d;
            if (storedData.players.TryGetValue(player.userID, out val) && (val > 100d || val == -50d || val == -25d)) return;
            string msg = string.Format(lang.GetMessage("firstconnectionmessage", this, player.UserIDString), (config.ProtectionTime / 3600d));
            if (config.UseGT && GameTipAPI != null) {
                GameTipAPI?.Call("ShowGameTip", player, msg, 10f, true);
            }
            else {
                player.SendConsoleCommand("gametip.showgametip", msg);
                timer.Once(10f, () => player.SendConsoleCommand("gametip.hidegametip"));
            }
            SendReply(player, msg);
        }
        private ulong FullOwner(BaseEntity ent, BasePlayer p = null) {
            if (ent == null) return 0u;
            var block = ent.GetComponent<BuildingBlock>();
            if (block == null) return ent.OwnerID;
            var cached = BuildingInfo.GetByBuildingID(block.buildingID);
            if (cached != null) if (cached.GetCacheAge() < 180 && cached.GetCacheAge() != -1) return cached.OwnerID;
            var ents = BaseEntity.saveList.Where(x => x.GetComponent<BuildingBlock>()?.buildingID == block.buildingID).ToList();
            var backup = ents.ToList();
            if (config.IgnoreTwig) ents.RemoveAll(x => (x as BuildingBlock)?.grade == BuildingGrade.Enum.Twigs);
            if (ents.Count == 0) ents = backup.ToList();
            Dictionary<ulong, int> ownership = new Dictionary<ulong, int>();
            foreach (var e in ents) {
                if (e.OwnerID == 0u) continue;
                var val = 0;
                if (!ownership.TryGetValue(e.OwnerID, out val)) ownership[e.OwnerID] = 1;
                else ownership[e.OwnerID]++;
            }
            if (ownership.Count == 0) {
                //Should this even happen?
                PrintWarning(lang.GetMessage("struct_noowner", this, null), ent.transform.position);
                return ent.OwnerID;
            }
            var owner = ownership.Max(x => x.Key);
            if (cached != null) {
                cached.OwnerID = owner;
                cached.lastUpdate = DateTime.UtcNow;
            }
            else BuildingInfo.buildCache.Add(new BuildingInfo {
                buildingID = block.buildingID, lastUpdate = DateTime.UtcNow, OwnerID = owner
            }
            );
            return owner;
        }
        private List<ulong> GetClanMembers(string clanName) {
            if (string.IsNullOrEmpty(clanName)) return new List<ulong>();
            var claninfo = ClanInfo.FindClanByName(clanName);
            if (claninfo != null) return claninfo.members;
            if (Clans == null) return new List<ulong>();
            List<ulong> IDlist = new List<ulong>();
            foreach (var p in covalence.Players.All) {
                string clan = Clans?.Call<string>("GetClanOf", p) ?? string.Empty;
                if (clan == clanName) IDlist.Add(ulong.Parse(p.Id));
            }
            RefreshClanCache();
            return IDlist;
        }
        private BaseEntity GetLookAtEntity(BasePlayer player, float maxDist = 10f) {
            if (player == null || player.IsDead()) return null;
            RaycastHit hit;
            var currentRot = Quaternion.Euler(player?.serverInput?.current?.aimAngles ?? Vector3.zero) * Vector3.forward;
            var ray = new Ray((player?.eyes?.position ?? Vector3.zero), currentRot);
            if (Physics.Raycast(ray, out hit, maxDist, layers)) {
                var ent = hit.GetEntity() ?? null;
                if (ent != null && !(ent?.IsDestroyed ?? true)) return ent;
            }
            return null;
        }
        private void LastConnect(ulong ID) => storedData.lastConnection[ID] = DateTime.Now.ToString();
        private void LogPlayer(BasePlayer attacker) {
            if (attacker == null) return;
            var val = 0;
            if (!storedData.AttackAttempts.TryGetValue(attacker.userID, out val)) storedData.AttackAttempts[attacker.userID] = 1;
            else storedData.AttackAttempts[attacker.userID]++;
        }
        private void MessagePlayer(BasePlayer attacker, ulong ID) {
            if (!storedData.players.ContainsKey(ID)) return;
            double time2 = storedData.players[ID];
            int left = (int)(config.ProtectionTime - time2);
            if (config.ShowMessage) {
                if (PlayerIsNew(ID)) {
                    if (config.ShowTime) {
                        SendReply(attacker, lang.GetMessage("cannot_attack_time", this, attacker.UserIDString), CheckLeft(left));
                        return;
                    }
                    SendReply(attacker, lang.GetMessage("cannot_attack_no_time", this, attacker.UserIDString));
                    return;
                }
                SendReply(attacker, lang.GetMessage("can_attack", this, attacker.UserIDString));
            }
        }
        private bool PlayerIsNew(ulong ID) {
            if (permission.UserHasPermission(ID.ToString(), NoobPerm)) return true;
            var outDouble = 0d;
            if (!storedData.players.TryGetValue(ID, out outDouble) || outDouble == -50d) return false;
            if (outDouble < config.ProtectionTime || outDouble == -25d) return true;
            return false;
        }
        private void RemoveCD(List<BasePlayer> List, BasePlayer player, float time = 0.1f) {
            if (player == null) return;
            timer.Once(time, () => {
                if (List.Contains(player)) List.Remove(player);
            }
            );
        }
        private void RemoveClanP(ulong ID) {
            if (ID == 0u) return;
            string clan = string.Empty;
            var claninfo = ClanInfo.GetClanOf(ID);
            if (claninfo != null) clan = claninfo.clanName;
            else clan = Clans?.Call<string>("GetClanOf", ID) ?? string.Empty;
            if (string.IsNullOrEmpty(clan)) return;
            var ClanMembers = ClanInfo.FindClanByName(clan)?.members ?? new List<ulong>();
            if (ClanMembers.Count < 1) return;
            var list = storedData.players.Where(x => x.Value != -50d && ClanMembers.Contains(x.Key));
            if (list.Count() < 1) return;
            foreach (var member in list) storedData.players[member.Key] = -50d;
            Puts(lang.GetMessage("clan_lostnoob", this, null), clan);
        }
        private void RemoveInactive() {
            foreach (var entry in storedData.lastConnection) {
                var val = 0d;
                if (string.IsNullOrEmpty(entry.Value) || !storedData.players.TryGetValue(entry.Key, out val)) continue;
                if (val == -50d) continue;
                var tp = DateTime.Now.Subtract(Convert.ToDateTime(entry.Value));
                if (tp.TotalDays > config.InactivityRemove) {
                    Puts(lang.GetMessage("console_lostnoobstatus", this, null), entry.Key, config.InactivityRemove);
                    storedData.players[entry.Key] = -50d;
                }
            }
        }
        private void Refund(BasePlayer attacker, string name, BaseEntity ent) {
            if (!config.Refund || storedData.ItemList.Count < 1) return;
            foreach (var entry in storedData.ItemList) {
                if (name == entry.Value) {
                    if (config.RefundTimes == 0) {
                        Item item = ItemManager.CreateByName(entry.Key, 1);
                        attacker.GiveItem(item);
                        SendReply(attacker, lang.GetMessage("refund_free", this, attacker.UserIDString), item.info.displayName.english);
                        return;
                    }
                    if ((storedData.AttackAttempts[attacker.userID]) <= config.RefundTimes) {
                        int a = config.RefundTimes - (storedData.AttackAttempts[attacker.userID]);
                        Item item = ItemManager.CreateByName(entry.Key, 1);
                        attacker.GiveItem(item);
                        switch (a) {
                            case 0 : {
                                SendReply(attacker, lang.GetMessage("refund_last", this, attacker.UserIDString), item.info.displayName.english);
                                return;
                            }
                            case 1 : {
                                SendReply(attacker, lang.GetMessage("refund_1time", this, attacker.UserIDString), item.info.displayName.english);
                                return;
                            }
                            default : {
                                SendReply(attacker, lang.GetMessage("refund_nTimes", this, attacker.UserIDString), item.info.displayName.english, a);
                                return;
                            }
                        }
                    }
                }
            }
        }
        private void StartChecking() {
            timer.Every(config.Frequency, () => {
                RemoveInactive();
                Check();
            }
            );
        }
        private void SteamCheck(ulong ID, bool connecting) {
            if (!config.CheckSteam) return;
            if (string.IsNullOrEmpty(config.ApiKey)) {
                Puts(lang.GetMessage("steam_wrongapikey", this, null));
                return;
            }
            string date = "[" + DateTime.Now.ToString() + "] ";
            if (storedData.players.ContainsKey(ID)) {
                if (storedData.players[ID] == -50d) {
                    LogToFile(this.Name, date + "Player " + ID + " is already marked as non noob", this, false);
                    return;
                }
                else if (storedData.players[ID] == -25d) {
                    LogToFile(this.Name, date + "Player " + ID + " is already marked as noob (-25)", this, false);
                    return;
                }
            }
            Puts(lang.GetMessage("steam_checkstart", this, null), ID);
            webrequest.Enqueue("http://api.steampowered.com/IPlayerService/GetOwnedGames/v0001/?key=" + config.ApiKey + "&steamid=" + ID, null, (code, response) => {
                if (code != 200) {
                    Puts(lang.GetMessage("steam_responsewrong", this, null));
                    LogToFile(this.Name, date + "Invalid response for " + ID + " (" + code + ")", this, false);
                    return;
                }
                var des = Utility.ConvertFromJson<SteamGames>(response);
                if (des?.response?.games == null) {
                    Puts(lang.GetMessage("steam_private", this, null), ID);
                    LogToFile(this.Name, date + "Steam profile of " + ID + " is private", this, false);
                    return;
                }
                foreach (var game in des.response.games) {
                    if (game.appid == 252490) {
                        double hours = game.playtime_forever / 60d;
                        if (connecting) Puts(lang.GetMessage("steam_connected", this, null), ID, System.Math.Round(hours, 2));
                        if (hours >= config.SteamInGameTime) {
                            Puts(lang.GetMessage("steam_marking", this, null), ID);
                            LogToFile(this.Name, date + ID + " has " + hours + "h in game", this, false);
                            if (!storedData.players.ContainsKey(ID)) {
                                LogToFile(this.Name, date + "Adding new entry for " + ID, this, false);
                                storedData.players.Add(ID, -50d);
                                return;
                            }
                            LogToFile(this.Name, date + "Overwriting existing entry for " + ID, this, false);
                            storedData.players[ID] = -50d;
                            return;
                        }
                        Puts(lang.GetMessage("console_notenough", this, null));
                    }
                }
            }
            , this);
        }
#endregion
#region Commands
        private Dictionary<string, string> AdminCommands = new Dictionary<string, string> {
            {
                "antinoob", "AntiNoobCommand"
            }
            , {
                "refunditem", "RefundCmd"
            }
        }
        ;
        private void AntiNoobCommand(IPlayer player, string command, string[] args) {
            if (args.Length < 1) {
                player.Reply(lang.GetMessage("antinoobcmd_syntax", this, player.Id));
                return;
            }
            switch (args[0].ToLower()) {
 
// ... [Code preview truncated due to length. Full source in attached file] ...

Автор
15FPS
Скачиваний
0
Просмотры
1
Первый выпуск
Обновление
Оценка
0.00 звёзд 0 оценок

Другие ресурсы пользователя 15FPS

Сверху