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

FREE HorseLock : 1.1.6 1.1.6

Нет прав для скачивания
C#:
using Newtonsoft.Json;
using Oxide.Core;
using Oxide.Core.Libraries.Covalence;
using Oxide.Core.Plugins;
using Rust;
using System;
using System.Collections.Generic;
using UnityEngine;
using System.Reflection;

/* Changelog

1.1.6
 - Fixed: Horse will now rear when unauthorized players attempt to lead or mount
 - Added: Config option to prevent horses losing health when in owners/teams building priv

1.1.5
 - Fixed: Updated for May 1st Rust update

1.1.4:
 - Fixed: Players being able to claim horses without buying in some cases
 - Added: Config option to set minimum time before warning player about unlock time (reduce chat notification spam)

1.1.3:
 - Fixed: Players being able to claim horses at Ranch without using a saddle

1.1.2:
 - Fixed: Unauthorised players are now unable to loot horse inventory

1.1.1:
 - Fixed: Use Friends, Clans and Teams options now work as intended when set to false

*/  

namespace Oxide.Plugins
{
    [Info("Horse Lock", "ZEODE", "1.1.6")]
    [Description("Lock ridable horses to players to prevent unauthorised use.")]
    public class HorseLock: RustPlugin
    {
        #region Plugin References
        
        [PluginReference] Plugin Friends, Clans, VehicleLicence;
        
        #endregion Plugin References

        #region Consts

        private const string horsePrefab = "assets/content/vehicles/horse/ridablehorse.prefab";
        private const string saddlePrefab = "assets/prefabs/vehicle/seats/horsesaddle.prefab";

        #endregion Consts

        #region Oxide Hooks

        private void Init()
        {
            try
            {
                storedData = Interface.Oxide.DataFileSystem.ReadObject<StoredData>(Name);
                
                if (storedData == null)
                {
                    Puts("Data is null. Creating blank data file...");
                    storedData = new StoredData();
                    SaveData();
                }
            }
            catch (Exception ex)
            {
                if (ex is JsonSerializationException || ex is NullReferenceException || ex is JsonReaderException || ex is KeyNotFoundException)
                {
                    Puts("Data file invalid. Creating blank data file...");
                    storedData = new StoredData();
                    SaveData();
                    return;
                }
                throw;
            }
        }

        private void Unload()
        {
            SaveData();
        }

        private void OnServerSave()
        {
            SaveData();
        }

        private void OnNewSave()
        {
            PrintWarning("Server wipe detected, clearing all player horse data.");
            storedData = new StoredData();
            SaveData();
        }

        private object CanMountEntity(BasePlayer player, BaseMountable mount)
        {
            if (player == null || mount == null)
                return null;

            if (mount.name.Equals(saddlePrefab) && player.userID.IsSteamId())
            {
                RidableHorse horse = mount?.GetParentEntity() as RidableHorse;
                if (horse == null)
                    return null;

                return CanMountOrLead(horse, player, false);
            }
            return null;
        }

        private object OnHorseLead(RidableHorse horse, BasePlayer player)
        {
            if (player == null || horse == null)
                return null;

            if (horse.name.Equals(horsePrefab) && player.userID.IsSteamId())
                return CanMountOrLead(horse, player, true);

            return null;
        }

        private object CanLootEntity(BasePlayer player, RidableHorse horse)
        {
            if (player == null || horse == null)
                return null;

            if (horse.name.Equals(horsePrefab) && player.userID.IsSteamId())
            {
                if (horse.IsForSale)
                    return null;

                return CanMountOrLead(horse, player, false);
            }
            return null;
        }

        private object OnEntityDismounted(BaseMountable entity, BasePlayer player)
        {
            if (player == null || entity == null)
                return null;

            if (entity.name.Equals(saddlePrefab) && player.userID.IsSteamId())
            {
                RidableHorse horse = entity?.GetParentEntity() as RidableHorse;
                if (horse == null || player == null)
                    return null;

                if (VehicleLicence && (bool)VehicleLicence?.CallHook("IsLicensedVehicle", horse))
                    return null;

                ulong ownerId = horse.OwnerID;
                ulong horseNetId = horse.net.ID.Value;

                float dismountTime;
                if (!storedData.playerData[ownerId].Horses.TryGetValue(horseNetId, out dismountTime))
                    return null;

                BasePlayer owner = FindPlayerByPartialNameOrId(ownerId.ToString());
                if (owner == null)
                    return null;

                if (Time.realtimeSinceStartup - storedData.playerData[ownerId].UnlockWarningTime >= config.options.warningTimeout)
                {
                    storedData.playerData[ownerId].UnlockWarningTime = Time.realtimeSinceStartup;
                    var horsePriv = horse?.GetBuildingPrivilege();
                    if (!horsePriv || !horsePriv.IsAuthed(ownerId))
                    {
                        TimeSpan time = TimeSpan.FromSeconds(config.options.lockTime);
                        Message(player, "DismountTimeSplit", time.ToString("hh"), time.ToString("mm"), time.ToString("ss"));
                    }
                }
                AddHorseData(owner.userID, owner.displayName, horseNetId);
            }
            return null;
        }

        private object OnEntityTakeDamage(RidableHorse horse, HitInfo info)
        {
            if (horse == null || info == null)
                return null;
            
            var damageType = info.damageTypes.GetMajorityDamageType();
            var damageAmount = info.damageTypes.Total();

            if (damageType == DamageType.Decay && config.options.privProtected)
            {
                BasePlayer owner = FindPlayerByPartialNameOrId(horse.OwnerID.ToString());
                if (owner == null)
                    return null;
                
                if (horse.GetBuildingPrivilege()?.IsAuthed(owner) == true)
                {
                    info.damageTypes.Clear();
                    return true;
                }
            }

            return null;
        }

        #endregion Oxide Hooks

        #region Helpers
        
        private object CanMountOrLead(RidableHorse horse, BasePlayer player, bool lead = false)
        {
            if (player == null || horse == null)
                return null;

            ulong playerId = player.userID;
            ulong ownerId = horse.OwnerID;
            string ownerName = GetOwnerDisplayName(horse);
            ulong horseNetId = horse.net.ID.Value;

            if (horse.name.Equals(horsePrefab) && player.userID.IsSteamId())
            {
                if (ownerId == 0)
                {
                    horse.OwnerID = playerId;
                    AddHorseData(playerId, player.displayName, horseNetId);
                    Message(player, "Claimed");
                    return null;
                }
                else if (VehicleLicence && (bool)VehicleLicence.CallHook("IsLicensedVehicle", horse))
                {
                    return null;
                }

                if(!storedData.playerData.ContainsKey(ownerId))
                    AddHorseData(ownerId, ownerName, horseNetId);
                
                float dismountTime;
                if (!storedData.playerData[ownerId].Horses.TryGetValue(horseNetId, out dismountTime))
                {
                    if (!IsFriend(ownerId, playerId))
                    {
                        if (config.options.doRear)
                            HorseRear(horse, player);
                        
                        Message(player, lead ? "NoLead" : "NoMountOrLoot", ownerName);
                        return true;
                    }
                    AddHorseData(ownerId, ownerName, horseNetId);
                }
                else if (storedData.playerData[ownerId].Horses.TryGetValue(horseNetId, out dismountTime))
                {
                    var horsePriv = horse?.GetBuildingPrivilege();
                    if (horsePriv && horsePriv.IsAuthed(ownerId))
                    {
                        if (!IsFriend(ownerId, playerId))
                        {
                            if (config.options.doRear)
                                HorseRear(horse, player);
                            
                            Message(player, lead ? "NoLead" : "NoMountOrLoot", ownerName);
                            return true;
                        }
                    }
                    else
                    {
                        float timeSinceDismount = Time.realtimeSinceStartup - storedData.playerData[ownerId].Horses[horseNetId];
                        if (timeSinceDismount > config.options.lockTime)
                        {
                            RemoveHorseData(ownerId, horseNetId);
                            horse.OwnerID = playerId;
                            AddHorseData(playerId, player.displayName, horseNetId);
                            Message(player, "TimedOut");
                            return null;
                        }
                        else if (!IsFriend(ownerId, playerId))
                        {
                            if (config.options.doRear)
                                HorseRear(horse, player);
                            
                            Message(player, lead ? "NoLead" : "NoMountOrLoot", ownerName);
                            return true;
                        }
                    }
                }
            }
            return null;
        }

        private void HorseRear(RidableHorse horse, BasePlayer player)
        {
            horse.duckDoubleTapped = true;
            horse.lastDuckTapTime = Time.time;
            horse.MovementsUpdate();
        }

        private bool IsFriend(ulong playerId, ulong targetId)
        {
            if (playerId == 0 || targetId == 0)
                return false;
            
            if (playerId == targetId)
                return true;
            
            if (config.options.useClans && Clans)
            {
                var result = Clans?.Call("IsMemberOrAlly", playerId, targetId);
                if (result != null && Convert.ToBoolean(result))
                    return true;
            }
            if (config.options.useFriends && Friends)
            {
                var result = Friends?.Call("AreFriends", playerId, targetId);
                if (result != null && Convert.ToBoolean(result))
                    return true;
            }
            if (config.options.useTeams)
            {
                RelationshipManager.PlayerTeam team;
                RelationshipManager.ServerInstance.playerToTeam.TryGetValue(playerId, out team);
                if (team == null)
                    return false;
                
                if (team.members.Contains(targetId))
                    return true;
            }
            
            return false;
        }

        BasePlayer FindPlayerByPartialNameOrId(string nameOrId)
        {
            if (string.IsNullOrEmpty(nameOrId))
                return null;

            IPlayer player = covalence.Players.FindPlayer(nameOrId);
            if (player != null)
                return (BasePlayer)player.Object;

            return null;
        }

        private string GetOwnerDisplayName(BaseEntity entity)
        {
            var playerID = entity.OwnerID;
            
            if (playerID.IsSteamId())
            {
                var player = FindPlayerByPartialNameOrId(playerID.ToString());
                if (player)
                    return player.displayName;

                var p = covalence.Players.FindPlayerById(playerID.ToString());
                if (p != null)
                    return p.Name;
            }

            return $"Unknown: {playerID}";
        }

        #endregion Helpers

        #region Language
        
        protected override void LoadDefaultMessages()
        {
            lang.RegisterMessages(new Dictionary<string, string>
            {
                ["NoLead"] = "You <color=red>cannot</color> lead this horse, it belongs to <color=green>{0}</color>.",
                ["NoMountOrLoot"] = "You <color=red>cannot</color> mount or loot this horse, it belongs to <color=green>{0}</color>.",
                ["Claimed"] = "This horse was unclaimed, you now <color=green>own</color> it!",
                ["DismountTimeSplit"] = "Horse will be unlocked in <color=red>{0} h : {1} m : {2} s</color> unless you mount again in that time or store within your building privilege.",
                ["TimedOut"] = "This horse was abandoned by it's previous owner, you now <color=green>own</color> it!"
            }, this);
        }

        private string Lang(string messageKey, string playerId, params object[] args) {
            return string.Format(lang.GetMessage(messageKey, this, playerId), args);
        }

        private void Message(BasePlayer player, string messageKey, params object[] args)
        {
            if (player == null || !player.userID.IsSteamId())
                return;
            
            var message = Lang(messageKey, player.UserIDString, args);
            Player.Message(player, message, config.options.usePrefix ? config.options.chatPrefix : null, config.options.chatIcon);
        }

        #endregion Language

        #region Stored Data

        private static StoredData storedData;

        private class StoredData
        {
            public Dictionary<ulong, PlayerData> playerData = new Dictionary<ulong, PlayerData>();
        }

        private class PlayerData
        {
            public string PlayerName;
            public ulong UserID;
            public float UnlockWarningTime;
            public Dictionary<ulong, float> Horses = new Dictionary<ulong, float>();
        }

        private void AddHorseData(ulong playerId, string playerName, ulong horseId)
        {
            if(!storedData.playerData.ContainsKey(playerId))
            {
                storedData.playerData.Add(playerId, new PlayerData());
                storedData.playerData[playerId].PlayerName = playerName;
                storedData.playerData[playerId].UserID = playerId;
                storedData.playerData[playerId].Horses.Add(horseId, Time.realtimeSinceStartup);
            }
            else
            {
                if (storedData.playerData[playerId].Horses.ContainsKey(horseId))
                    storedData.playerData[playerId].Horses[horseId] = Time.realtimeSinceStartup;
                else
                    storedData.playerData[playerId].Horses.Add(horseId, Time.realtimeSinceStartup);
            }
        }

        private void RemoveHorseData(ulong playerId, ulong horseId)
        {
            if (storedData.playerData.ContainsKey(playerId))
            {
                if (storedData.playerData[playerId].Horses.ContainsKey(horseId))
                    storedData.playerData[playerId].Horses.Remove(horseId);
            }
        }

        private void SaveData()
        {
            Interface.Oxide.DataFileSystem.WriteObject(Name, storedData);
        }

        #endregion Stored Data

        #region Config

        private static ConfigData config;

        private class ConfigData
        {
            [JsonProperty(PropertyName = "Options")]
            public Options options;
            
            public class Options
            {
                [JsonProperty(PropertyName = "Use Chat Prefix")]
                public bool usePrefix { get; set; }
                [JsonProperty(PropertyName = "Chat Prefix")]
                public string chatPrefix { get; set; }
                [JsonProperty(PropertyName = "Use Friends Plugin (Friends Can Mount)")]
                public bool useFriends { get; set; }
                [JsonProperty(PropertyName = "Use Clans Plugin (Clan Can Mount)")]
                public bool useClans { get; set; }
                [JsonProperty(PropertyName = "Use Teams (Team Can Mount)")]
                public bool useTeams { get; set; }
                [JsonProperty(PropertyName = "Custom Chat Icon (Default = 0)")]
                public ulong chatIcon { get; set; }
                [JsonProperty(PropertyName = "Time Horse Locked After Dismount (Seconds)")]
                public float lockTime { get; set; }
                [JsonProperty(PropertyName = "Minimum Time Between Dismount Unlock Warnings (Seconds)")]
                public float warningTimeout { get; set; }
                [JsonProperty(PropertyName = "Make Horse Rear When Unauthorised Player Attempts to Mount")]
                public bool doRear { get; set; }
                [JsonProperty(PropertyName = "Horses Within Building Privilege Do Not Lose Health")]
                public bool privProtected { get; set; }
            }

            [JsonProperty(PropertyName = "Plugin Version")]
            public VersionNumber pluginVersion { get; set; }
        }

        private ConfigData GetDefaultConfig()
        {
            return new ConfigData
            {
                options = new ConfigData.Options
                {
                    usePrefix = true,
                    chatPrefix = "[Horse Lock]: ",
                    useFriends = false,
                    useClans = false,
                    useTeams = false,
                    chatIcon = 0,
                    lockTime = 900f,
                    warningTimeout = 120f,
                    doRear = true,
                    privProtected = false
                },
                pluginVersion = Version
            };
        }

        protected override void LoadConfig()
        {
            base.LoadConfig();
            try
            {
                config = Config.ReadObject<ConfigData>();
                if (config == null)
                    LoadDefaultConfig();
                else if (config.pluginVersion < Version)
                    UpdateConfigValues();
            }
            catch (Exception ex)
            {
                if (ex is JsonSerializationException || ex is NullReferenceException || ex is JsonReaderException)
                {
                    Puts($"ERROR: {ex}");
                    return;
                }
                throw;
            }
        }

        protected override void LoadDefaultConfig()
        {
            Puts("Configuration file missing or corrupt, creating default config file.");
            config = GetDefaultConfig();
        }
        
        protected override void SaveConfig()
        {
            Config.WriteObject(config);
        }

        private void UpdateConfigValues()
        {
            ConfigData defaultConfig = GetDefaultConfig();

            Puts("Config update detected! Updating config file...");
            if (config.pluginVersion < new VersionNumber(1, 0, 1))
            {
                config = defaultConfig;
            }
            if (config.pluginVersion < new VersionNumber(1, 1, 4))
            {
                config.options.warningTimeout = defaultConfig.options.warningTimeout;
            }
            if (config.pluginVersion < new VersionNumber(1, 1, 6))
            {
                config.options.privProtected = defaultConfig.options.privProtected;
            }
            Puts("Config update completed!");
            config.pluginVersion = Version;
            SaveConfig();
        }

        #endregion Config
    }
}

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