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

FREE AntiCheat : 2.3.7 2.3.7

Нет прав для скачивания
C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using System.Collections.Generic;
using System;
using System.Reflection;
using System.Data;
using UnityEngine;
using Oxide.Core;
using Oxide.Core.Plugins;
using Rust;

namespace Oxide.Plugins
{
    [Info("AntiCheat", "Reneb & 4Seti", "2.3.7", ResourceId = 730)]
    class AntiCheat : RustPlugin
    {

        ////////////////////////////////////////////////////////////
        // Plugin References
        ////////////////////////////////////////////////////////////

        [PluginReference]
        Plugin EnhancedBanSystem;

        [PluginReference]
        Plugin DeadPlayersList;

        [PluginReference]
        Plugin Jail;

        static bool jailExists = false;

        ////////////////////////////////////////////////////////////
        // Cached Fields
        ////////////////////////////////////////////////////////////

        static RaycastHit cachedRaycasthit;
        Dictionary<string, string> deadPlayers = new Dictionary<string, string>();
        Hash<ulong, BasePlayer> cachedPlayers = new Hash<ulong, BasePlayer>();

        ////////////////////////////////////////////////////////////
        // Static Fields
        ////////////////////////////////////////////////////////////

        static DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0);

        static DamageTypeList emptyDamage = new DamageTypeList();

        static Vector3 VectorDown = new Vector3(0f, -1f, 0f);

        static int flyColl;
        static int constructionColl;
        static int bulletmask;

        ////////////////////////////////////////////////////////////
        // Fields
        ////////////////////////////////////////////////////////////

        Oxide.Plugins.Timer activateTimer;

        bool serverInitialized = false;

        static List<BasePlayer> adminList = new List<BasePlayer>();

        static bool fpsCheckCalled = false;
        static ConsoleSystem.Arg fpsCaller;
        static List<PlayerHack> fpsCalled = new List<PlayerHack>();
        static double fpsTime;

        ////////////////////////////////////////////////////////////
        // Config Fields
        ////////////////////////////////////////////////////////////

        static int authIgnore = 1;
        static int fpsIgnore = 30;
        static bool banFamilyShare = true;
        static int punishType = 1;
        static float resetTime = 60f;

        static bool speedhack = true;
        static bool speedhackPunish = true;
        static int speedhackDetections = 3;
        static float minSpeedPerSecond = 10f;
        static bool speedhackLog = true;

        static bool flyhack = true;
        static bool flyhackPunish = true;
        static int flyhackDetections = 3;
        static bool flyhackLog = true;

        static bool wallhack = true;
        static bool wallhackPunish = true;
        static bool wallhackLog = true;
        static int wallhackDetections = 2;

        static bool wallhackkills = true;
        static bool wallhackkillsLog = true;

        static bool meleespeedhack = true;


        static string multipleNames = "Multiple players found with this name";
        static string noPlayerFound = "No player found with this name";

        ////////////////////////////////////////////////////////////
        // Config Management
        ////////////////////////////////////////////////////////////

        protected override void LoadDefaultConfig() { }

        private void CheckCfg<T>(string Key, ref T var)
        {
            if (Config[Key] is T)
                var = (T)Config[Key];
            else
                Config[Key] = var;
        }
        private void CheckCfgFloat(string Key, ref float var)
        {

            if (Config[Key] != null)
                var = Convert.ToSingle(Config[Key]);
            else
                Config[Key] = var;
        }

        void Init()
        {
            CheckCfg<int>("Settings: Ignore Hacks for authLevel", ref authIgnore);
            CheckCfg<int>("Settings: Punish - 0 = Kick, 1 = Ban, 2 = Jail", ref punishType);
            CheckCfg<int>("Settings: FPS Ignore", ref fpsIgnore);
            CheckCfg<bool>("Settings: Ban Also Family Owner", ref banFamilyShare);
            CheckCfg<bool>("MeleeSpeed Hack: activated", ref meleespeedhack);
            CheckCfg<bool>("SpeedHack: activated", ref speedhack);
            CheckCfg<bool>("SpeedHack: Punish", ref speedhackPunish);
            CheckCfg<bool>("SpeedHack: Log", ref speedhackLog);
            CheckCfg<int>("SpeedHack: Punish Detections", ref speedhackDetections);
            CheckCfgFloat("SpeedHack: Speed Detection", ref minSpeedPerSecond);
            CheckCfg<bool>("Flyhack: activated", ref flyhack);
            CheckCfg<bool>("Flyhack: Punish", ref flyhackPunish);
            CheckCfg<bool>("Flyhack: Log", ref flyhackLog);
            CheckCfg<int>("Flyhack: Punish Detections", ref flyhackDetections);
            CheckCfg<bool>("Wallhack: activated", ref wallhack);
            CheckCfg<bool>("Wallhack: Punish", ref wallhackPunish);
            CheckCfg<bool>("Wallhack: Log", ref wallhackLog);
            CheckCfg<int>("Wallhack: Punish Detections", ref wallhackDetections);

            CheckCfg<bool>("Wallhack Kills: activated", ref wallhackkills);
            CheckCfg<bool>("Wallhack Kills: Log", ref wallhackkillsLog);
            SaveConfig();
        }

        ////////////////////////////////////////////////////////////
        // Log Management
        ////////////////////////////////////////////////////////////

        static StoredData storedData;
        static Hash<string, List<AntiCheatLog>> anticheatlogs = new Hash<string, List<AntiCheatLog>>();

        class StoredData
        {
            public HashSet<AntiCheatLog> AntiCheatLogs = new HashSet<AntiCheatLog>();

            public StoredData()
            {
            }
        }

        void OnServerSave()
        {
            SaveData();
        }

        void SaveData()
        {
            Interface.GetMod().DataFileSystem.WriteObject("AntiCheatLogs", storedData);
        }

        void LoadData()
        {
            anticheatlogs.Clear();
            try
            {
                storedData = Interface.GetMod().DataFileSystem.ReadObject<StoredData>("AntiCheatLogs");
            }
            catch
            {
                storedData = new StoredData();
            }
            foreach (var thelog in storedData.AntiCheatLogs)
            {
                if (anticheatlogs[thelog.userid] == null)
                    anticheatlogs[thelog.userid] = new List<AntiCheatLog>();
                (anticheatlogs[thelog.userid]).Add(thelog);
            }
        }

        public class AntiCheatLog
        {
            public string userid;
            public string fx;
            public string fy;
            public string fz;
            public string tx;
            public string ty;
            public string tz;
            public string td;
            public string lg;

            Vector3 frompos;
            Vector3 topos;

            public AntiCheatLog()
            {
            }

            public AntiCheatLog(string userid, string logType, Vector3 frompos, Vector3 topos)
            {
                this.userid = userid;
                this.fx = frompos.x.ToString();
                this.fy = frompos.y.ToString();
                this.fz = frompos.z.ToString();
                this.tx = topos.x.ToString();
                this.ty = topos.y.ToString();
                this.tz = topos.z.ToString();
                this.td = logType;
                this.lg = LogTime().ToString();
            }

            public Vector3 FromPos()
            {
                if (frompos == default(Vector3))
                    frompos = new Vector3(float.Parse(fx), float.Parse(fy), float.Parse(fz));
                return frompos;
            }

            public Vector3 ToPos()
            {
                if (topos == default(Vector3))
                    topos = new Vector3(float.Parse(tx), float.Parse(ty), float.Parse(tz));
                return topos;
            }
        }

        static void AddLog(string userid, string logType, Vector3 frompos, Vector3 topos)
        {
            if (anticheatlogs[userid] == null)
                anticheatlogs[userid] = new List<AntiCheatLog>();
            AntiCheatLog newlog = new AntiCheatLog(userid, logType, frompos, topos);
            (anticheatlogs[userid]).Add(newlog);
            storedData.AntiCheatLogs.Add(newlog);
        }

        static double LogTime() { return DateTime.UtcNow.Subtract(epoch).TotalSeconds; }


        ////////////////////////////////////////////////////////////
        // Oxide Hooks
        ////////////////////////////////////////////////////////////

        ////////////////////////////////////////////////////////////
        // Plugin Initialization
        ////////////////////////////////////////////////////////////

        void Loaded()
        {
            constructionColl = UnityEngine.LayerMask.GetMask(new string[] { "Construction" });
            flyColl = UnityEngine.LayerMask.GetMask(new string[] { "Construction", "Deployed", "Tree", "Terrain", "Resource", "World", "Water" });

            if (!permission.PermissionExists("cananticheat")) permission.RegisterPermission("cananticheat", this);
        }


        ////////////////////////////////////////////////////////////
        // Server Initialization
        ////////////////////////////////////////////////////////////

        void OnServerInitialized()
        {
            serverInitialized = true;
            if(Jail != null) jailExists = true;

            LoadData();

            timer.Once(1f, () => RefreshPlayers());
        }

        ////////////////////////////////////////////////////////////
        // Plugin Unload
        ////////////////////////////////////////////////////////////

        void Unload()
        {
            DestroyAll<PlayerHack>();
            DestroyAll<ColliderCheckTest>();
            DestroyAll<PlayerLog>();
            if (activateTimer != null)
                activateTimer.Destroy();
        }

        void DestroyAll<T>()
        {
            UnityEngine.Object[] objects = GameObject.FindObjectsOfType(typeof(T));
            if (objects != null)
                foreach (UnityEngine.Object gameObj in objects)
                    GameObject.Destroy(gameObj);
        }

        ////////////////////////////////////////////////////////////
        // OnPlayerRespawned
        // Called when a player respawns (after death)
        ////////////////////////////////////////////////////////////
        void OnPlayerRespawned(BasePlayer player)
        {
            RefreshPlayer(player);
        }

        ////////////////////////////////////////////////////////////
        // OnPlayerInit
        // Called when a player enters the world
        ////////////////////////////////////////////////////////////
        void OnPlayerInit(BasePlayer player)
        {
            if(player.net != null && player.net.connection != null)
            {
                RefreshPlayer( player );
                if (isAdmin(player)) { if (!adminList.Contains(player)) adminList.Add(player); }
            }
        }

        ////////////////////////////////////////////////////////////
        // OnPlayerDisconnected
        // Called when a player disconnects from the server
        ////////////////////////////////////////////////////////////
        void OnPlayerDisconnected(BasePlayer player)
        {
            if (adminList.Contains(player)) adminList.Remove(player);
        }

        ////////////////////////////////////////////////////////////
        // Random Functions
        ////////////////////////////////////////////////////////////

        bool isAdmin( BasePlayer player )
        {
            if (player.net.connection.authLevel > 0) return true;
            return permission.UserHasPermission(player.userID.ToString(), "cananticheat");
        }
        static double CurrentTime()
        {
            return DateTime.UtcNow.Subtract(epoch).TotalMilliseconds;
        }


        ////////////////////////////////////////////////////////////
        // Refresh Players
        ////////////////////////////////////////////////////////////

        void RefreshPlayers()
        {
            foreach (BasePlayer player in BasePlayer.activePlayerList)
            {
                RefreshPlayer( player );
                if( isAdmin(player) ) { if (!adminList.Contains(player)) adminList.Add(player); }
            }
        }

        void RefreshPlayer(BasePlayer player)
        {
            if (isAdmin(player)) return;
            if (wallhack) MakeTestCollider( player );
            if (speedhack || flyhack)
                if (player.GetComponent<PlayerHack>() == null)
                    player.gameObject.AddComponent<PlayerHack>();
        }

        ////////////////////////////////////////////////////////////
        // PlayerHack class
        ////////////////////////////////////////////////////////////

        public class PlayerHack : MonoBehaviour
        {
            public BasePlayer player;

            public Vector3 lastPosition;
            public Vector3 currentDirection;

            public bool isonGround;
            public bool wasGround = true;


            public float Distance3D;
            public float VerticalDistance;
            public float deltaTick;
            public float flyHackDetections = 0f;
            public float speedHackDetections = 0f;

            public double currentTick;
            public double lastTick;
            public double lastTickFly;
            public double lastTickSpeed;

            void Awake()
            {
                player = GetComponent<BasePlayer>();
                InvokeRepeating("CheckPlayer", 1f, 1f);
                lastPosition = player.transform.position;
            }
            void CheckPlayer()
            {
                if (!player.IsConnected()) GameObject.Destroy(this);
                currentTick = CurrentTime();
                deltaTick = (float)((currentTick - lastTick)/1000.0);
                Distance3D = Vector3.Distance(player.transform.position, lastPosition)/deltaTick;
                VerticalDistance = (player.transform.position.y - lastPosition.y)/deltaTick;
                currentDirection = (player.transform.position - lastPosition).normalized;
                isonGround = player.IsOnGround();

                if (!player.IsWounded() && !player.IsDead() && !player.IsSleeping() && deltaTick < 1.1f && Performance.frameRate > fpsIgnore)
                    CheckForHacks(this);

                lastPosition = player.transform.position;

                if (fpsCheckCalled)
                    if (!fpsCalled.Contains(this))
                    {
                        fpsCalled.Add(this);
                        fpsTime += (CurrentTime() - currentTick);
                    }

                lastTick = currentTick;
            }
        }
        static void CheckForHacks(PlayerHack hack)
        {
            if (speedhack)
                CheckForSpeedHack(hack);
            if (flyhack)
                CheckForFlyhack(hack);
        }

        ////////////////////////////////////////////////////////////
        // Wallhack related
        ////////////////////////////////////////////////////////////

        Hash<ulong, ColliderCheckTest> playerWallcheck = new Hash<ulong, ColliderCheckTest>();

        static Hash<BuildingBlock, float> createdBuilding = new Hash<BuildingBlock, float>();
        static Hash<uint, float> DoorCheck = new Hash<uint, float>();
        static Hash<BasePlayer, float> lastWallhack = new Hash<BasePlayer, float>();
        static Hash<BasePlayer, int> wallhackDetec = new Hash<BasePlayer, int>();

        static bool isOpen(BuildingBlock block)
        {

            if (block.net != null && block.net.ID != null)
                if (Time.realtimeSinceStartup - DoorCheck[block.net.ID] < 6f)
                    return true;
            if(block.blockDefinition.hierachyName.StartsWith("block"))
                return true;

            switch(block.blockDefinition.hierachyName)
            {
                case "wall.doorway":
                    foreach( Collider collider in UnityEngine.Physics.OverlapSphere(block.transform.position, 2f) )
                    {
                        if(collider.GetComponentInParent<Door>() != false)
                        {
                            if (Time.realtimeSinceStartup - DoorCheck[collider.GetComponentInParent<BuildingBlock>().net.ID] < 6f)
                            {
                                return true;
                            }
                        }
                    }
                break;
                default:
                break;
            }

            return false;
        }

        void OnDoorOpened(BuildingBlock door) { DoorCheck[door.net.ID] = Time.realtimeSinceStartup; }

        void OnDoorClosed(BuildingBlock door) { DoorCheck[door.net.ID] = Time.realtimeSinceStartup; }

        public class ColliderCheckTest : MonoBehaviour
        {
            public BasePlayer player;
            Hash<Collider, Vector3> entryPosition = new Hash<Collider, Vector3>();
            SphereCollider col;
            public float teleportedBack;
            public Collider lastCollider;

            void Awake()
            {
                player = transform.parent.GetComponent<BasePlayer>();

                col = gameObject.AddComponent<SphereCollider>();
                col.radius = 0.1f;
                col.isTrigger = true;
                col.center = new Vector3(0f, 0.5f, 0f);
            }
            void OnTriggerEnter(Collider collision)
            {
                if( Time.realtimeSinceStartup < teleportedBack + 0.2f && collision != lastCollider ) return;
                if( hasBuildingPrivileges( player ) ) return;
                if( collision.GetComponentInParent<BuildingBlock>() )
                {
                    BuildingBlock block = collision.GetComponentInParent<BuildingBlock>();
                    if(block != null)
                    {
                        if(Time.realtimeSinceStartup - createdBuilding[block] > 20)
                        {
                            if(!isOpen(block))
                                entryPosition[collision] = player.transform.position;
                        }
                    }
                    else
                    {
                        entryPosition[collision] = player.transform.position;
                    }
                }
            }

            void OnTriggerExit(Collider collision)
            {
                if(entryPosition.ContainsKey(collision))
                {
                    BuildingBlock block = collision.GetComponentInParent<BuildingBlock>();

                    Interface.GetMod().LogWarning(string.Format("AntiCheat: {0} was detected colliding with {1}", player.displayName, (block!=null) ? block.blockDefinition.hierachyName : collision.gameObject.name));

                    ForcePlayerBack(this, collision, entryPosition[collision], player.transform.position);

                    if(Time.realtimeSinceStartup - lastWallhack[player] < 10f)
                    {
                        SendDetection(string.Format("{0} - {1} is being detected with: Wallhack ({2})", player.userID.ToString(), player.displayName, (block!=null) ? block.blockDefinition.hierachyName : collision.gameObject.name));
                        if (wallhackLog)
                            AddLog(player.userID.ToString(), "wall", entryPosition[collision], player.transform.position);
                        if(wallhackPunish)
                        {
                            wallhackDetec[player]++;
                            if(wallhackDetec[player] >= wallhackDetections)
                            {
                                Punish(player, string.Format("rWallhack ({0})", (block!=null) ? block.blockDefinition.hierachyName : collision.gameObject.name));
                            }
                        }
                    }
                    else if(wallhackPunish)
                        wallhackDetec[player] = 0;

                    lastWallhack[player] = Time.realtimeSinceStartup;
                    entryPosition.Remove(collision);
                }
            }

            void OnDestroy()
            {
                GameObject.Destroy(gameObject);
                GameObject.Destroy(col);
            }
        }
           static bool hasBuildingPrivileges(BasePlayer player)
           {
               return player.HasPlayerFlag(BasePlayer.PlayerFlags.HasBuildingPrivilege);
           }

        static void ForcePlayerBack(ColliderCheckTest colcheck, Collider collision, Vector3 entryposition, Vector3 exitposition)
        {
            Vector3 rollBackPosition = GetRollBackPosition(entryposition, exitposition, 4f);
            Vector3 rollDirection = (entryposition - exitposition).normalized;
            foreach( RaycastHit rayhit in UnityEngine.Physics.RaycastAll( rollBackPosition, (exitposition - entryposition).normalized, 5f ))
            {
                if(rayhit.collider == collision)
                {
                    rollBackPosition = rayhit.point + rollDirection*1f;
                }
            }
            colcheck.teleportedBack = Time.realtimeSinceStartup;
            colcheck.lastCollider = collision;
            ForcePlayerPosition(colcheck.player, rollBackPosition );
        }
        static Vector3 GetRollBackPosition( Vector3 entryposition, Vector3 exitposition, float distance)
        {
            distance = Vector3.Distance(exitposition, entryposition) + distance;
            var direction = (entryposition - exitposition).normalized;
            return (exitposition + (direction * distance));
        }

        static void ForcePlayerPosition(BasePlayer player, Vector3 destination)
        {

            player.transform.position = destination;
            player.ClientRPCPlayer(null, player, "ForcePositionTo", new object[] { destination });
            player.TransformChanged();
        }

        void OnEntityBuilt(Planner planner, GameObject gameobject)
        {
            if (!wallhack) return;
            if (!serverInitialized) return;
            BuildingBlock buildingblock = gameobject.GetComponentInParent<BuildingBlock>();
            if (buildingblock == null) return;
            createdBuilding[buildingblock] = Time.realtimeSinceStartup;
        }

        void MakeTestCollider(BasePlayer player, bool force = false)
        {
            if(player == null) return;

            if(playerWallcheck[player.userID] != null)
            {
                GameObject.Destroy(playerWallcheck[player.userID]);
                playerWallcheck[player.userID] = null;
            }

            if(player.transform != null && player.transform.position != null)
            {
                if(player.net.connection.authLevel < 1 || force)
                {
                    var newObject = new GameObject("ColliderTest");
                    newObject.transform.position = player.transform.position;
                    newObject.transform.parent = player.transform;
                    playerWallcheck[player.userID] = newObject.AddComponent<ColliderCheckTest>();
                }
            }
        }

        ////////////////////////////////////////////////////////////
        // Speedhack related
        ////////////////////////////////////////////////////////////

        static void CheckForSpeedHack(PlayerHack hack)
        {
            if (hack.Distance3D < minSpeedPerSecond) return;
            if (hack.VerticalDistance < -8f) return;
            if (hack.lastTickSpeed == hack.lastTick)
            {
                hack.speedHackDetections++;
                if (speedhackLog)
                    AddLog(hack.player.userID.ToString(), "speed", hack.lastPosition, hack.player.transform.position);
                SendDetection(string.Format("{0} - {1} is being detected with: Speedhack ({2}m/s)", hack.player.userID.ToString(), hack.player.displayName, hack.Distance3D.ToString()));
                if (hack.speedHackDetections >= speedhackDetections)
                {
                    if (speedhackPunish)
                        Punish(hack.player, string.Format("rSpeedhack ({0}m/s)", hack.Distance3D.ToString()));
                }

            }
            else
            {
                hack.speedHackDetections = 0f;
            }
            hack.lastTickSpeed = hack.currentTick;
        }

        ////////////////////////////////////////////////////////////
        // Flyhack related
        ////////////////////////////////////////////////////////////

        static void CheckForFlyhack(PlayerHack hack)
        {
            if (hack.isonGround) return;
            if (hack.Distance3D != 0f && hack.VerticalDistance < -5f && hack.VerticalDistance/hack.Distance3D < -0.5) return;
            if (UnityEngine.Physics.Raycast(hack.player.transform.position, VectorDown, 3f)) { hack.wasGround = true; return; }
            foreach(Collider col in UnityEngine.Physics.OverlapSphere(hack.player.transform.position, 2f, flyColl)) { hack.wasGround = true; return; }
            if (WaterLevel.Factor(hack.player.GetComponent<Collider>()) > 0) return;
            if (!hack.wasGround && hack.lastTickFly == hack.lastTick)
            {
                hack.flyHackDetections++;
                if (flyhackLog)
                    AddLog(hack.player.userID.ToString(), "fly", hack.lastPosition, hack.player.transform.position);
                SendDetection(string.Format("{0} - {1} is being detected with: Flyhack ({2}m/s)", hack.player.userID.ToString(), hack.player.displayName, hack.Distance3D.ToString()));
                if (hack.flyHackDetections >= flyhackDetections)
                {
                    if (flyhackPunish)
                        Punish(hack.player, string.Format("rFlyhack ({0}m/s)", hack.Distance3D.ToString()));
                }
            }
            else
            {
                hack.flyHackDetections = 0f;
            }
            hack.wasGround = false;
            hack.lastTickFly = hack.currentTick;
        }

        ////////////////////////////////////////////////////////////
        // Wallhack Kills related
        ////////////////////////////////////////////////////////////

        void WallhackKillCheck(BasePlayer player, BasePlayer attacker, HitInfo hitInfo)
        {
            if (Physics.Linecast(attacker.eyes.position, hitInfo.HitPositionWorld, out cachedRaycasthit, bulletmask))
            {
                BuildingBlock block = cachedRaycasthit.collider.GetComponentInParent<BuildingBlock>();
                if (block != null)
                {
                    if(block.blockDefinition.hierachyName == "wall.window") return;

                    CancelDamage(hitInfo);
                    if (Time.realtimeSinceStartup - lastWallhack[attacker] > 0.5f)
                    {
                        lastWallhack[attacker] = Time.realtimeSinceStartup;
                        SendDetection(string.Format("{0} - {1} is being detected killing {2} through a wall", attacker.userID.ToString(), attacker.displayName, player.displayName));

                        if (wallhackkillsLog)
                            AddLog(attacker.userID.ToString(), "wallkill", attacker.eyes.position, hitInfo.HitPositionWorld);
                    }
                }
            }
        }


        void OnBasePlayerAttacked(BasePlayer player, HitInfo hitInfo)
        {
            if (!wallhackkills) return;
            if (player.IsDead()) return;
            if (hitInfo.Initiator == null) return;
            if (player.health - hitInfo.damageTypes.Total() > 0f) return;
            BasePlayer attacker = hitInfo.Initiator.ToPlayer();
            if (attacker == null) return;
            if (attacker == player) return;
            WallhackKillCheck(player, attacker, hitInfo);
        }
        void CancelDamage(HitInfo hitinfo)
        {
            hitinfo.damageTypes = emptyDamage;
            hitinfo.HitEntity = null;
        }

        ////////////////////////////////////////////////////////////
        // Anti OverKill related
        ////////////////////////////////////////////////////////////

        public Hash<BasePlayer, double> lastAttack = new Hash<BasePlayer, double>();
        public Hash<BasePlayer, int> attackSpeedDetections = new Hash<BasePlayer, int>();

        void OnMeleeAttack(BaseMelee melee, HitInfo info)
        {
            var thetime = Time.realtimeSinceStartup;
            BasePlayer attacker = melee.GetParentEntity() as BasePlayer;
            if (attacker == null) return;

            if (meleespeedhack)
            {
                if ((CurrentTime() - lastAttack[attacker]) < melee.repeatDelay - 0.2)
                {
                        CancelDamage(info);
                        attackSpeedDetections[attacker]++;
                        if(attackSpeedDetections[attacker] > 1)
                            SendDetection(string.Format("{0} - {1} was detected hiting too fast - @ {2}", attacker.userID.ToString(), attacker.displayName.ToString(), attacker.transform.position.ToString()));
                }
                else
                    attackSpeedDetections[attacker] = 0;

                lastAttack[attacker] = CurrentTime();
            }
        }

        ////////////////////////////////////////////////////////////
        // Admin Chat related
        ////////////////////////////////////////////////////////////

        static void SendDetection(string msg)
        {
            foreach (BasePlayer player in adminList)
            {
                if (player != null && player.net != null)
                {
                    player.SendConsoleCommand("chat.add", new object[] { 0, msg.QuoteSafe() });
                }
            }
            Interface.GetMod().LogWarning(msg);
        }
        static void SendMsgAdmin(string msg)
        {
            foreach (BasePlayer player in adminList)
            {
                if (player != null && player.net != null)
                {
                    player.SendConsoleCommand("chat.add", new object[] { 0, msg.QuoteSafe() });
                }
            }
        }



        ////////////////////////////////////////////////////////////
        // Punish a player
        ////////////////////////////////////////////////////////////

        void Ban(object source, BasePlayer target, string msg, bool theboolean)
        {
            if (EnhancedBanSystem != null) return;
            ServerUsers.Set(target.userID, ServerUsers.UserGroup.Banned, target.displayName, msg);
            ServerUsers.Save();

            //ConsoleSystem.Broadcast("chat.add", new object[] { 0, "<color=orange>AntiCheat:</color> " + msg });

            PrintWarning(string.Format("{0}[{1}] banned by AntiCheat", target.displayName, target.userID));
            Network.Net.sv.Kick(target.net.connection, "Banned for hacking");
        }

        static void Punish(BasePlayer player, string msg)
        {
            if (player.net.connection.authLevel < authIgnore)
            {
                if (punishType == 1)
                {
                    if (banFamilyShare)
                        if (player.net.connection.ownerid != player.userID)
                        {
                            ServerUsers.Set(player.net.connection.ownerid, ServerUsers.UserGroup.Banned, player.displayName, msg);
                            ServerUsers.Save();
                        }
                    Interface.GetMod().CallHook("Ban", null, player, msg, false);
                }
                else if(punishType == 2 && jailExists )
                {
                    Interface.CallHook("AddPlayerToJail", player, -1);
                    Interface.CallHook("SendPlayerToJail", player);
                }
                else
                    player.Kick(msg);
            }
            else
            {
                GameObject.Destroy(player.GetComponent<PlayerHack>());
            }
        }

        bool hasAccess(BasePlayer player)
        {
            if (player == null) return false;
            if (player.net.connection.authLevel > 0) return true;
            return permission.UserHasPermission(player.userID.ToString(), "cananticheat");
        }

        void RefreshBasePlayers()
        {
            cachedPlayers.Clear();
            foreach( BasePlayer player in Resources.FindObjectsOfTypeAll(typeof(BasePlayer)) )
            {
                cachedPlayers.Add(player.userID, player);
            }
        }

        bool FindPlayerByID(string userID, out string targetname)
        {
            ulong userid;
            targetname = string.Empty;
            if (!(userID.Length == 17 && ulong.TryParse(userID, out userid)))
                return false;
            if(cachedPlayers[userid] != null) targetname = (cachedPlayers[userid]).displayName;
            if(targetname != string.Empty)
                return true;
            if (deadPlayers == null)
                return false;
            if(!deadPlayers.ContainsKey(userID))
                return false;
            targetname = deadPlayers[userID];
            return true;
        }

        bool FindPlayerByName(string name, out string targetid, out string targetname)
        {
            ulong userid;
            targetid = string.Empty;
            targetname = string.Empty;
            if (name.Length == 17 && ulong.TryParse(name, out userid))
            {
                targetid = name;
                return true;
            }

            foreach (BasePlayer player in Resources.FindObjectsOfTypeAll(typeof(BasePlayer)))
            {
                if (player.displayName == name)
                {
                    targetid = player.userID.ToString();
                    targetname = player.displayName;
                    return true;
                }
                if (player.displayName.Contains(name))
                {
                    if (targetid == string.Empty)
                    {
                        targetid = player.userID.ToString();
                        targetname = player.displayName;
                    }
                    else
                    {
                        targetid = multipleNames;
                    }
                }
            }
            if (targetid == multipleNames)
                return false;
            if (targetid != string.Empty)
                return true;
            targetid = noPlayerFound;
            if (DeadPlayersList == null)
                return false;
            deadPlayers = DeadPlayersList.Call("GetPlayerList", null) as Dictionary<string, string>;
            if (deadPlayers == null)
                return false;

            foreach (KeyValuePair<string, string> pair in deadPlayers)
            {
                if (pair.Value == name)
                {
                    targetid = pair.Key;
                    targetname = pair.Value;
                    return true;
                }
                if (pair.Value.Contains(name))
                {
                    if (targetid == noPlayerFound)
                    {
                        targetid = pair.Key;
                        targetname = pair.Value;
                    }
                    else
                    {
                        targetid = multipleNames;
                    }
                }
            }
            if (targetid == multipleNames)
                return false;
            if (targetid != noPlayerFound)
                return true;
            return false;
        }

        ////////////////////////////////////////////////////////////
        // Log Class
        ////////////////////////////////////////////////////////////
        public class AcLog
        {
            public Vector3 frompos;
            public string message;
            public Vector3 topos;

            public AcLog(Vector3 frompos, Vector3 topos, string message )
            {
                this.frompos = frompos;
                this.topos = topos;
                this.message = message;
            }
        }


        public class PlayerLog : MonoBehaviour
        {
            public BasePlayer player;
            public Vector3 lastPosition;
            public List<AcLog> logs = new List<AcLog>();


            void Awake()
            {
                player = GetComponent<BasePlayer>();
                InvokeRepeating("CheckLogs", 1f, 2f);
            }
            void CheckLogs()
            {
                if (!player.IsConnected()) { GameObject.Destroy(this); return; }
                foreach(AcLog log in logs)
                {
                    player.SendConsoleCommand("ddraw.arrow", 2f, UnityEngine.Color.red, log.frompos, log.topos, 0.5f);
                    if (log.message != string.Empty)
                    {

                        player.SendConsoleCommand("ddraw.text", 2f, UnityEngine.Color.white, log.frompos, log.message);
                    }

                }
            }
            public void Clear()
            {
                logs.Clear();
            }
            public void AddLog(AntiCheatLog aclog, string targetid)
            {
                string detectionText = string.Empty;
                switch (aclog.td)
                {
                    case "speed":
                        detectionText = string.Format("{0} - speed - {1}m/s", targetid, Vector3.Distance(aclog.ToPos(), aclog.FromPos()).ToString());
                        break;
                    case "fly":
                        detectionText = string.Format("{0} - fly - {1}m/s", targetid, Vector3.Distance(aclog.ToPos(), aclog.FromPos()).ToString());
                        break;
                    case "wall":
                        detectionText = string.Format("{0} - wall", targetid);
                        break;
                    case "wallkill":
                        detectionText = string.Format("{0} - wallkill", targetid);
                    break;
                    default:

                        break;
                }
                logs.Add(new AcLog(aclog.FromPos(), aclog.ToPos(), detectionText));
            }
        }

        void TeleportAdmin(BasePlayer player, Vector3 destination)
        {
            player.StartSleeping();
            player.transform.position = destination;
            player.ClientRPCPlayer(null, player, "ForcePositionTo", new object[] { destination });
            player.TransformChanged();

            player.SetPlayerFlag(BasePlayer.PlayerFlags.ReceivingSnapshot, true);
            player.UpdateNetworkGroup();
            player.UpdatePlayerCollider(true, false);
            player.SendNetworkUpdateImmediate(false);
            player.ClientRPCPlayer(null, player, "StartLoading");
            player.SendFullSnapshot();
            player.SetPlayerFlag(BasePlayer.PlayerFlags.ReceivingSnapshot, false);
            player.ClientRPCPlayer(null, player, "FinishLoading");

        }

        ////////////////////////////////////////////////////////////
        // Chat Commands
        ////////////////////////////////////////////////////////////

        [ChatCommand("ac")]
        void cmdChatAC(BasePlayer player, string command, string[] args)
        {
            if (!hasAccess(player)) { SendReply(player, "You dont have access to this command"); return; }
            if (args == null || args.Length < 2)
            {
                if (player.GetComponent<PlayerLog>())
                {
                    SendReply(player, "Deactivated AntiCheat Log Viewer.");
                    GameObject.Destroy(player.GetComponent<PlayerLog>());
                    return;
                }
                SendReply(player, "/ac player PLAYERNAME/STEAMID => to show all the hack detections made by this player");
                SendReply(player, "/ac radius RADIUS => to show all hack detections in this radius.");
                return;
            }

            if (args[0].ToLower() == "player")
            {
                PlayerLog playerlog = player.GetComponent<PlayerLog>();
                if (playerlog == null)
                    playerlog = player.gameObject.AddComponent<PlayerLog>();
                string targetid = string.Empty;
                string targetname = string.Empty;
                if (!FindPlayerByName(args[1], out targetid, out targetname))
                {
                    SendReply(player, targetid);
                    return;
                }
                if (anticheatlogs[targetid] == null || (anticheatlogs[targetid]).Count == 0)
                {
                    SendReply(player, string.Format("{0} {1} - has no hack detections", targetid, targetname));
                    return;
                }
                SendReply(player, string.Format("{0} {1} - has {2} hack detections", targetid, targetname, (anticheatlogs[targetid]).Count.ToString()));
                string detectionText = string.Empty;
                foreach (AntiCheatLog aclog in anticheatlogs[targetid])
                {
                    playerlog.AddLog(aclog, targetid);
                }
                SendReply(player, string.Format("You may say: /ac_tp NUMBER, to teleport to the specific detection (0-{0})", (playerlog.logs.Count - 1).ToString()));
            }
            else if (args[0].ToLower() == "radius")
            {
                PlayerLog playerlog = player.GetComponent<PlayerLog>();
                if (playerlog == null)
                    playerlog = player.gameObject.AddComponent<PlayerLog>();
                float radius = 20f;
                if(!float.TryParse(args[1],out radius))
                {
                    SendReply(player, "/ac radius XXX");
                    return;
                }
                string detectionText = string.Empty;
                playerlog.Clear();
                foreach ( KeyValuePair<string, List<AntiCheatLog>> pair in anticheatlogs)
                {
                    foreach(AntiCheatLog aclog in pair.Value)
                    {
                        if(Vector3.Distance(player.transform.position, aclog.FromPos()) < radius )
                        {
                            playerlog.AddLog(aclog, pair.Key);
                        }
                    }
                }
                SendReply(player, string.Format("{0} detections were made in a {1}m radius around you",playerlog.logs.Count.ToString(),radius.ToString()));
                SendReply(player, string.Format("You may say: /ac_tp NUMBER, to teleport to the specific detection (0-{0})",(playerlog.logs.Count-1).ToString()));
            }
            else
            {
                SendReply(player, string.Format("This argument: \"{0}\" doesn't exist", args[0]));
            }
        }

        [ChatCommand("ac_tp")]
        void cmdChatACTP(BasePlayer player, string command, string[] args)
        {
            if (!hasAccess(player)) { SendReply(player, "You dont have access to this command"); return; }
            PlayerLog playerlog = player.GetComponent<PlayerLog>();
            if (playerlog == null)
            {
                SendReply(player, "You must use /ac player NAME/STEAMID or /ac radius XXX before using this command");
                return;
            }
            if(playerlog.logs == null  || playerlog.logs.Count == 0)
            {
                SendReply(player, "Couldn't find any logs in your current log list, use /ac first");
                return;
            }
            if(args.Length == 0)
            {
                SendReply(player, string.Format("You must select the number of the detection you want to teleport to (0-{0})",(playerlog.logs.Count-1).ToString()));
                return;
            }
            int lognumber = 0;
            if(!int.TryParse(args[0], out lognumber))
            {
                SendReply(player, string.Format("You must select the number of the detection you want to teleport to (0-{0})",(playerlog.logs.Count-1).ToString()));
                return;
            }
            if(lognumber < 0 || lognumber >= playerlog.logs.Count)
            {
                SendReply(player, string.Format("You must select a number of the detection between 0 and {0}",(playerlog.logs.Count-1).ToString()));
                return;
            }
            if(Vector3.Distance(player.transform.position, playerlog.logs[lognumber].frompos) < 100f)
                ForcePlayerPosition(player, playerlog.logs[lognumber].frompos);
            else
                TeleportAdmin(player, playerlog.logs[lognumber].frompos);
            SendReply(player, string.Format("{0} - {1} - {2}", playerlog.logs[lognumber].message.ToString(), playerlog.logs[lognumber].frompos.ToString(), playerlog.logs[lognumber].topos.ToString()));
        }

        [ChatCommand("ac_list")]
        void cmdChatACList(BasePlayer player, string command, string[] args)
        {
            if (!hasAccess(player)) { SendReply(player, "You dont have access to this command"); return; }
            string targetname = string.Empty;
            deadPlayers = DeadPlayersList?.Call("GetPlayerList", null) as Dictionary<string, string>;
            RefreshBasePlayers();
            foreach (KeyValuePair<string, List<AntiCheatLog>> pair in anticheatlogs)
            {
                targetname = string.Empty;
                if(!FindPlayerByID(pair.Key, out targetname))
                    targetname = "Unknown";
                SendReply(player, string.Format("{0} - {1} - {2} detections", pair.Key, targetname, pair.Value.Count.ToString()));
            }

            SaveData();
        }

        [ChatCommand("ac_remove")]
        void cmdChatACRemove(BasePlayer player, string command, string[] args)
        {
            if (!hasAccess(player)) { SendReply(player, "You dont have access to this command"); return; }
            string targetid = string.Empty;
            string targetname = string.Empty;
            if (!FindPlayerByName(args[0], out targetid, out targetname))
            {
                SendReply(player, targetid);
                return;
            }
            if (anticheatlogs[targetid] == null || (anticheatlogs[targetid]).Count == 0)
            {
                SendReply(player, string.Format("{0} {1} - has no hack detections", targetid, targetname));
                return;
            }

            foreach (AntiCheatLog aclog in anticheatlogs[targetid])
            {
                storedData.AntiCheatLogs.Remove(aclog);
            }
            anticheatlogs.Remove(targetid);
            SendReply(player, string.Format("Removed: {0} {1} anticheat logs", targetid, targetname));
            SaveData();
        }

        [ChatCommand("ac_reset")]
        void cmdChatACReset(BasePlayer player, string command, string[] args)
        {
            if (!hasAccess(player)) { SendReply(player, "You dont have access to this command"); return; }
            anticheatlogs.Clear();
            storedData.AntiCheatLogs.Clear();
            SaveData();
            SendReply(player, "AntiCheat: Logs were resetted");
        }

        [ChatCommand("actest")]
        void ttest(BasePlayer player, string command, string[] args)
        {
            MakeTestCollider(player, true);
        }
        ////////////////////////////////////////////////////////////
        // Console Commands
        ////////////////////////////////////////////////////////////

        [Con
// ... [Code preview truncated due to length. Full source in attached file] ...

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