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

FREE VoteBan : 1.0.1 1.0.1

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

#if RUST
using Facepunch;
#endif

using Newtonsoft.Json;

using Oxide.Core;
using Oxide.Core.Libraries.Covalence;

using UnityEngine;

using Time = UnityEngine.Time;

namespace Oxide.Plugins
{
    [Info("Vote Ban", "2CHEVSKII", "1.0.1")]
    [Description("Allows players to vote for banning others")]
    class VoteBan : CovalencePlugin
    {
        #region Fields

        const string M_PREFIX                 = "Chat prefix",
                     M_VOTE_STARTED           = "Vote started",
                     M_VOTE_PROGRESS          = "Vote in progress",
                     M_VOTED                  = "Voted",
                     M_ALREADY_VOTED          = "Voted already",
                     M_NO_PERMISSION          = "No permission",
                     M_NO_VOTE                = "No active vote",
                     M_VOTE_TIMED_OUT         = "Vote timed out",
                     M_VOTE_SUCCESS           = "Vote success",
                     M_VOTE_CANCELLED         = "Vote cancelled",
                     M_VOTE_CANCELLED_PLAYERS = "Vote cancelled (insufficient player count)",
                     M_BAN_REASON             = "Ban reason",
                     M_CANNOT_START_ADMIN     = "Vote cannot be started (cannot vote-out admins)",
                     M_CANNOT_START_PLAYERS   = "Vote cannot be started (insufficient player count)",
                     M_PLAYER_NOT_FOUND       = "Player not found",
                     M_CANNOT_VOTE_SELF       = "Cannot vote-out self";

        const string PERMISSION_MANAGE = "voteban.manage",
                     PERMISSION_VOTE   = "voteban.vote";

        PluginSettings settings;
        VoteData       voteData;

        #endregion

        #region Oxide hooks

        void Init()
        {
            permission.RegisterPermission(PERMISSION_MANAGE, this);
            permission.RegisterPermission(PERMISSION_VOTE, this);

            AddCovalenceCommand("voteban", nameof(CommandHandler));
        }

        #endregion

        #region Plugin API

        void OnVoteStarted(IPlayer initiator, IPlayer target)
        {
            Interface.Oxide.CallHook("OnVotebanStarted", initiator, target, settings.VoteTime);
            Announce(M_VOTE_STARTED, initiator.Name, target.Name, settings.VoteTime);
        }

        void OnPlayerVoted(IPlayer player)
        {
            Interface.Oxide.CallHook("OnVotebanPlayerVoted", player);
            Message(player, M_VOTED, voteData.voteTarget.Name);
        }

        void OnVoteTick()
        {
            Interface.Oxide.CallHook(
                "OnVotebanTick",
                voteData.voteInitiator,
                voteData.voteTarget,
                voteData.VoteFraction,
                voteData.VotedPlayerCount,
                voteData.TimeLeft
            );

            Announce(
                M_VOTE_PROGRESS,
                voteData.voteInitiator.Name,
                voteData.voteTarget.Name,
                Mathf.FloorToInt(voteData.VoteFraction * 100),
                voteData.VotedPlayerCount,
                GetPlayersRequiredToVoteSuccess(GetPlayerCountWithoutTarget(voteData.voteTarget)),
                Mathf.CeilToInt(voteData.TimeLeft)
            );
        }

        void OnVoteCancelled(IPlayer canceller = null)
        {
            if (canceller != null)
            {
                Interface.Oxide.CallHook(
                    "OnVotebanCancelled",
                    voteData.voteInitiator,
                    voteData.voteTarget,
                    (int)VoteData.CancelReason.Manual,
                    canceller
                );

                Announce(M_VOTE_CANCELLED, canceller.Name, voteData.voteInitiator.Name, voteData.voteTarget.Name);
            }
            else
            {
                Interface.Oxide.CallHook(
                    "OnVotebanCancelled",
                    voteData.voteInitiator,
                    voteData.voteTarget,
                    (int)VoteData.CancelReason.InsufficientPlayers
                );

                Announce(
                    M_VOTE_CANCELLED_PLAYERS,
                    voteData.voteInitiator.Name,
                    voteData.voteTarget.Name,
                    GetPlayerCountWithoutTarget(voteData.voteTarget),
                    settings.MinPlayers
                );
            }
        }

        void OnVoteTimedOut()
        {
            Interface.Oxide.CallHook("OnVotebanTimedOut", voteData.voteTarget);

            Announce(M_VOTE_TIMED_OUT, voteData.voteInitiator.Name, voteData.voteTarget.Name, settings.VoteTime);
        }

        void OnVoteSuccess()
        {
            Interface.Oxide.CallHook("OnVotebanSuccess", voteData.voteInitiator, voteData.voteTarget);

            Announce(M_VOTE_SUCCESS, voteData.voteInitiator.Name, voteData.voteTarget.Name);

            voteData.voteTarget.Ban(GetMessage(voteData.voteTarget, M_BAN_REASON));
        }

        bool IsVotebanInProgress()
        {
            return voteData != null;
        }

        bool GetCurrentVotebanData(Dictionary<string, object> record)
        {
            if (record == null)
            {
                throw new ArgumentNullException();
            }

            if (!IsVotebanInProgress())
            {
                return false;
            }

            record["initiator"] = voteData.voteInitiator;
            record["target"] = voteData.voteTarget;
            record["fraction"] = voteData.VoteFraction;
            record["required_fraction"] = settings.PercentageRequired / 100f;
            record["voted_players"] = voteData.votedPlayers.ToArray();
            record["required_voted_players"] = Mathf.RoundToInt(GetPlayerCountWithoutTarget(voteData.voteTarget) * (float)record["required_fraction"]);
            record["time_left"] = voteData.TimeLeft;
            record["start_time"] = voteData.startTime;
            record["end_time"] = voteData.endTime;

            return true;
        }

        #endregion

        #region Command handlers

        void CommandHandler(IPlayer player, string _, string[] args)
        {
            if (args.Length == 0)
            {
                HandleVoteCommand(player);
            }
            else
            {
                HandleManageCommand(player, args[0]);
            }
        }

        void HandleVoteCommand(IPlayer player)
        {
            if (CheckPermission(player, PERMISSION_VOTE))
            {
                if (voteData == null)
                {
                    Message(player, M_NO_VOTE);
                    return;
                }

                if (voteData.voteTarget.Id.Equals(player.Id))
                {
                    Message(player, M_CANNOT_VOTE_SELF);
                    return;
                }

                if (!voteData.CanPlayerVote(player))
                {
                    Message(player, M_ALREADY_VOTED);
                    return;
                }

                voteData.OnPlayerVoted(player);
            }
        }

        void HandleManageCommand(IPlayer player, string arg)
        {
            if (voteData != null)
            {
                switch (arg.ToLower())
                {
                    case "end":
                    case "cancel":
                        if (CheckPermission(player, PERMISSION_MANAGE))
                        {
                            voteData.CancelVote(player);
                        }

                        break;
                    default:
                        Message(
                            player,
                            M_VOTE_PROGRESS,
                            voteData.voteInitiator.Name,
                            voteData.voteTarget.Name,
                            (int)(voteData.VoteFraction * 100),
                            voteData.VotedPlayerCount,
                            GetPlayersRequiredToVoteSuccess(GetPlayerCountWithoutTarget(voteData.voteTarget))
                        );
                        break;
                }
            }
            else if (CheckPermission(player, PERMISSION_MANAGE))
            {
                IPlayer target = players.FindPlayer(arg);

                if (target == null)
                {
                    Message(player, M_PLAYER_NOT_FOUND, arg);
                }
                else if (target.Id.Equals(player.Id))
                {
                    Message(player, M_CANNOT_VOTE_SELF);
                }
                else if (target.IsAdmin && !settings.AllowBanningAdmins)
                {
                    Message(player, M_CANNOT_START_ADMIN);
                }
                else
                {
                    int playerCount = GetPlayerCountWithoutTarget(target);
                    if (playerCount < settings.MinPlayers)
                    {
                        Message(player, M_CANNOT_START_PLAYERS, playerCount, settings.MinPlayers);
                    }
                    else
                    {
                        voteData = new VoteData(player, target, this);
                    }
                }
            }
        }

        #endregion

        #region Utility

        int GetPlayerCountWithoutTarget(IPlayer target)
        {
            return players.Connected.Count(p => p != target);
        }

        int GetPlayersRequiredToVoteSuccess(int playerCount)
        {
            return Mathf.RoundToInt(settings.PercentageRequired / 100f * playerCount);
        }

        bool CheckPermission(IPlayer player, string perm)
        {
            if (player.HasPermission(perm))
            {
                return true;
            }

            Message(player, M_NO_PERMISSION);

            return false;
        }

        #endregion

        #region LangAPI

        string GetMessage(IPlayer player, string langKey)
        {
            return lang.GetMessage(langKey, this, player.Id);
        }

        void Message(IPlayer player, string langKey, params object[] args)
        {
            string prefix = GetMessage(player, M_PREFIX);
            string format = GetMessage(player, langKey);

            string message = prefix + string.Format(format, args);

            player.Message(message);
        }

        void Announce(string langKey, params object[] args)
        {
            foreach (IPlayer player in players.Connected)
            {
                Message(player, langKey, args);
            }
        }

        protected override void LoadDefaultMessages()
        {
            lang.RegisterMessages(
                new Dictionary<string, string> {
                    [M_PREFIX] = "[VoteBan] ",
                    [M_NO_PERMISSION] = "You are not allowed to use this command",
                    [M_VOTE_STARTED] = "{0} has started the vote to ban {1}, use /voteban to vote for it",
                    [M_VOTE_PROGRESS] =
                        "Vote to ban {1} is in progress, use /voteban to vote for it.Current vote progress: {2}% ({3}/{4}), time left: {5} seconds",
                    [M_VOTED] = "You've voted for banning player {0}",
                    [M_ALREADY_VOTED] = "You've voted already",
                    [M_NO_VOTE] = "No active vote found",
                    [M_VOTE_TIMED_OUT] = "Vote to ban player {1} was unsuccessful, not enough players voted for it",
                    [M_VOTE_SUCCESS] =
                        "Vote to ban player {1} was successful, player will now be banned from the server",
                    [M_VOTE_CANCELLED] = "{0} has cancelled the vote for banning player {2}",
                    [M_VOTE_CANCELLED_PLAYERS] =
                        "Vote for banning player {1} was cancelled because of insufficient player count ({2}/{3})",
                    [M_BAN_REASON] = "You've been voted-out",
                    [M_CANNOT_START_ADMIN] = "Ban vote cannot be started against admins",
                    [M_CANNOT_START_PLAYERS] = "Not enough players on the server to start a vote ({0}/{1})",
                    [M_PLAYER_NOT_FOUND] = "Vote target ({0}) was not found",
                    [M_CANNOT_VOTE_SELF] = "You cannot vote against yourself"
                },
                this
            );
        }

        #endregion

        #region Configuration

        protected override void LoadDefaultConfig()
        {
            settings = PluginSettings.Default;
            SaveConfig();
        }

        protected override void LoadConfig()
        {
            base.LoadConfig();

            try
            {
                settings = Config.ReadObject<PluginSettings>();

                if (settings == null)
                {
                    throw new Exception("Configuration is null");
                }

                if (settings.PercentageRequired > 100 || settings.PercentageRequired < 1)
                {
                    LogWarning("Required vote percentage must be in range of 1..100");
                    settings.PercentageRequired = 50;
                }

                if (settings.VoteTime < 5)
                {
                    LogWarning("Vote time cannot be less than 5 seconds");
                    settings.VoteTime = 5;
                }

                if (settings.NotificationFrequency < 5)
                {
                    LogWarning("Notification frequency cannot be less than 5 seconds");
                    settings.NotificationFrequency = 5;
                }
            }
            catch (Exception e)
            {
                LogError("Failed to load configuration: {0}", e.Message);
                LoadDefaultConfig();
            }
        }

        protected override void SaveConfig()
        {
            Config.WriteObject(settings);
        }

        #endregion

        #region PluginSettings

        class PluginSettings
        {
            public static PluginSettings Default => new PluginSettings {
                VoteTime = 600,
                NotificationFrequency = 30,
                MinPlayers = 5,
                PercentageRequired = 70,
                AllowBanningAdmins = false
            };

            [JsonProperty("Vote time")] public int VoteTime { get; set; }

            [JsonProperty("Notification frequency")]
            public int NotificationFrequency { get; set; }

            [JsonProperty("Min player count to start vote")]
            public int MinPlayers { get; set; }

            [JsonProperty("Vote success percentage")]
            public int PercentageRequired { get; set; }

            [JsonProperty("Allow banning admins")] public bool AllowBanningAdmins { get; set; }
        }

        #endregion

        #region VoteData

        class VoteData
        {
            public readonly IPlayer       voteTarget;
            public readonly IPlayer       voteInitiator;
            public          List<IPlayer> votedPlayers;
            public          float         startTime;
            public          float         endTime;

            readonly        VoteBan       plugin;
            Timer                         voteTimer;

            public int VotedPlayerCount => votedPlayers.Count;
            public float VoteFraction => (float)VotedPlayerCount / plugin.GetPlayerCountWithoutTarget(voteTarget);
            public float TimeLeft => endTime - Time.realtimeSinceStartup;

            public VoteData(IPlayer initiator, IPlayer target, VoteBan plugin)
            {
                this.plugin = plugin;
                voteTarget = target;
                voteInitiator = initiator;
#if RUST
                votedPlayers = Pool.GetList<IPlayer>();
#else
                votedPlayers = new List<IPlayer>();
#endif

                StartVote();
            }

            public void OnPlayerVoted(IPlayer player)
            {
                votedPlayers.Add(player);
                plugin.OnPlayerVoted(player);

                if (VoteFraction >= plugin.settings.PercentageRequired / 100f)
                {
                    plugin.OnVoteSuccess();
                    EndVote();
                }
            }

            public bool CanPlayerVote(IPlayer player)
            {
                return !votedPlayers.Contains(player);
            }

            public void CancelVote(IPlayer canceller)
            {
                plugin.OnVoteCancelled(canceller);
                EndVote();
            }

            void StartVote()
            {
                startTime = Time.realtimeSinceStartup;
                endTime = startTime + plugin.settings.VoteTime;

                voteTimer = plugin.timer.Every(plugin.settings.NotificationFrequency, VoteTick);

                votedPlayers.Add(voteInitiator);

                plugin.OnVoteStarted(voteInitiator, voteTarget);
            }

            void VoteTick()
            {
                if (Time.realtimeSinceStartup < endTime)
                {
                    if (plugin.GetPlayerCountWithoutTarget(voteTarget) < plugin.settings.MinPlayers)
                    {
                        plugin.OnVoteCancelled();
                        EndVote();
                    }
                    else
                    {
                        plugin.OnVoteTick();
                    }
                }
                else
                {
                    plugin.OnVoteTimedOut();
                    EndVote();
                }
            }

            void EndVote()
            {
                voteTimer.Destroy();
#if RUST
                Pool.FreeList(ref votedPlayers);
#endif
                plugin.voteData = null;
            }

            public enum CancelReason
            {
                Manual,
                InsufficientPlayers
            }
        }

        #endregion
    }
}

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