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

FREE Arena : 2.0.24 2.0.24

Нет прав для скачивания
C#:
// Requires: ArenaUI

using CompanionServer;
using Facepunch;
using Network;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Oxide.Core;
using Oxide.Core.Configuration;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using UnityEngine;
using UI = Oxide.Plugins.ArenaUI.UI;
using UI4 = Oxide.Plugins.ArenaUI.UI4;

///Скачано с дискорд сервера Rust Edit [PRO+]
///discord.gg/9vyTXsJyKR

namespace Oxide.Plugins
{
    using ArenaEx;

    [Info("Arena", "discord.gg/9vyTXsJyKR", "2.0.24"), Description("The core mechanics for arena combat games")]
    public class Arena : RustPlugin
    {
        #region Fields  
        [PluginReference]
        internal Plugin Economics, Kits, NoEscape, RotatingPickups, ServerRewards, Spawns, ZoneManager;


        private int scrapItemId;

        private static Regex hexFilter;

        private static DropOnDeath dropOnDeath = DropOnDeath.Nothing;

        public Hash<string, IEventPlugin> EventModes { get; set; } = new Hash<string, IEventPlugin>();

        public Hash<string, BaseEventGame> ActiveEvents { get; set; } = new Hash<string, BaseEventGame>();


        public EventData Events { get; private set; }

        private RestoreData Restore { get; set; }

        private LobbyHandler Lobby { get; set; }

        public static Arena Instance { get; private set; }

        public static ConfigData Configuration { get; set; }


        public static bool IsUnloading { get; private set; }


        internal const string ADMIN_PERMISSION = "arena.admin";

        internal const string BLACKLISTED_PERMISSION = "arena.blacklisted";

        private const string RESPAWN_BAG_CMD = "respawn_sleepingbag";
        private const string REMOVE_BAG_CMD = "respawn_sleepingbag_remove";
        private const string RESPAWN_CMD = "respawn";

        private const uint LOBBY_BAG_ID = 113;
        #endregion

        #region Oxide Hooks
        private void Loaded()
        {
            LoadData();

            permission.RegisterPermission(ADMIN_PERMISSION, this);

            permission.RegisterPermission(BLACKLISTED_PERMISSION, this);

            hexFilter = new Regex("^([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$");
                        
            Instance = this;

            IsUnloading = false;
        }

        protected override void LoadDefaultMessages() => lang.RegisterMessages(Messages, this);

        private void OnServerInitialized()
        {
            if (!CheckDependencies())
                return;

            if (Configuration.Server.DisableServerEvents)
                ConVar.Server.events = false;

            if (!Configuration.Server.UseChat)
                Unsubscribe(nameof(OnPlayerChat));

            if (!Configuration.Event.AddToTeams)
            {
                Unsubscribe(nameof(OnTeamLeave));
                Unsubscribe(nameof(OnTeamDisband));
                Unsubscribe(nameof(OnTeamInvite));
                Unsubscribe(nameof(OnTeamCreate));
            }

            Lobby = new LobbyHandler(Configuration.Lobby.LobbySpawnfile);

            scrapItemId = ItemManager.FindItemDefinition("scrap").itemid;
            dropOnDeath = ParseType<DropOnDeath>(Configuration.Event.DropOnDeath);

            foreach (BasePlayer player in BasePlayer.activePlayerList)
                OnPlayerConnected(player);

            Debug.Log($"[Arena] - Loading event games in 5 seconds...");
            timer.In(5, InitializeEvents);
        }

        private void Unload()
        {
            IsUnloading = true;

            SaveRestoreData();

            foreach (BaseEventGame baseEventGame in ActiveEvents.Values)
                UnityEngine.Object.Destroy(baseEventGame);

            BaseEventPlayer[] eventPlayers = UnityEngine.Object.FindObjectsOfType<BaseEventPlayer>();
            for (int i = 0; i < eventPlayers?.Length; i++)
                UnityEngine.Object.DestroyImmediate(eventPlayers[i]);

            DestroyTeleporters();

            hexFilter = null;          
            Configuration = null;
            Instance = null;
        }

        private void OnServerSave() => SaveRestoreData();
        #endregion

        #region Player Connect/Disconnect
        private void OnPlayerConnected(BasePlayer player)
        {
            if (Configuration.Server.RestorePlayers)
                TryRestorePlayer(player);

            if (Lobby.ForceLobbyRespawn && player.IsDead())
            {
                NextTick(() => Lobby.SendRespawnOptions(player));
                return;
            }

            if (Lobby.ForceLobbyRespawn && Configuration.Lobby.KeepPlayersInLobby && !player.IsAdmin && !permission.UserHasPermission(player.UserIDString, ADMIN_PERMISSION))
            {
                if (ZoneManager && !ZoneManager.Call<bool>("IsPlayerInZone", Configuration.Lobby.LobbyZoneID, player))
                    Lobby.TeleportToLobby(player);
            }
        }

        private void OnPlayerDisconnected(BasePlayer player)
        {
            BaseEventPlayer eventPlayer = GetUser(player);
            if (eventPlayer)            
                eventPlayer.Event.LeaveEvent(player);            
        }

        private void OnPlayerRespawned(BasePlayer player)
        {
            if (Configuration.Server.RestorePlayers)
                TryRestorePlayer(player);
        }

        private void TryRestorePlayer(BasePlayer player)
        {
            if (player.IsSleeping() || player.HasPlayerFlag(BasePlayer.PlayerFlags.ReceivingSnapshot))
            {
                timer.Once(1f, () => OnPlayerConnected(player));
                return;
            }

            UnlockClothingSlots(player);

            if (Restore.HasRestoreData(player.userID))
                Restore.RestorePlayer(player);
        }

        private object OnDefaultItemsReceive(PlayerInventory playerInventory) => Lobby.ForceLobbyRespawn && !Configuration.Server.RestorePlayers ? (object)true : null;
        #endregion

        #region Damage
        private void OnEntityTakeDamage(BaseEntity entity, HitInfo hitInfo)
        {
            if (!entity || hitInfo == null)
                return;

            BasePlayer player = entity.ToPlayer();

            if (player != null)
            {
                BaseEventPlayer eventPlayer = GetUser(player);
                if (eventPlayer)
                {
                    eventPlayer.Event.OnPlayerTakeDamage(eventPlayer, hitInfo);                   
                }
            }
            else
            {
                BaseEventPlayer attacker = GetUser(hitInfo.InitiatorPlayer);
                if (attacker != null)
                {
                    if (attacker.Event.CanDealEntityDamage(attacker, entity, hitInfo))
                        return;

                    ClearDamage(hitInfo);
                }
            }
        }

        // TruePVE bypass
        private object CanEntityTakeDamage(BaseCombatEntity baseCombatEntity, HitInfo hitInfo)
        {
            if (!baseCombatEntity || !(baseCombatEntity is BasePlayer))
                return null;

            return GetUser((baseCombatEntity as BasePlayer)) != null ? (object)true : null;
        }

        private object CanBeWounded(BasePlayer player, HitInfo hitInfo)
        {
            BaseEventPlayer eventPlayer = GetUser(player);
            if (eventPlayer)
                return false;
            return null;
        }

        private object OnPlayerDeath(BasePlayer player, HitInfo hitInfo)
        {
            if (player != null)
            {
                BaseEventPlayer eventPlayer = GetUser(player);
                if (eventPlayer)
                {
                    if (!eventPlayer.IsDead)
                        eventPlayer.Event.PrePlayerDeath(eventPlayer, hitInfo);
                    return false;
                }
            }
            return null;
        }

        private void OnEntityDeath(BasePlayer player, HitInfo hitInfo)
        {
            if (Lobby.ForceLobbyRespawn)
                NextTick(() => Lobby.SendRespawnOptions(player));
        }
        #endregion

        #region Spectate
        private object CanSpectateTarget(BasePlayer player, string name)
        {
            BaseEventPlayer eventPlayer = player.GetComponent<BaseEventPlayer>();
            if (eventPlayer && eventPlayer.Player.IsSpectating())
            {                
                eventPlayer.UpdateSpectateTarget();
                return false;
            }
            return null;
        }
        #endregion

        #region Spawned Entities
        private void OnEntityBuilt(Planner planner, GameObject gameObject)
        {
            BasePlayer player = planner?.GetOwnerPlayer();
            if (!player)
                return;

            BaseCombatEntity baseCombatEntity = gameObject?.ToBaseEntity() as BaseCombatEntity;
            if (baseCombatEntity == null)
                return;

            BaseEventPlayer eventPlayer = GetUser(player);
            if (eventPlayer)
                eventPlayer.Event.OnEntityDeployed(baseCombatEntity);
        }

        private void OnItemDeployed(Deployer deployer, BaseCombatEntity baseCombatEntity)
        {
            BasePlayer player = deployer.GetOwnerPlayer();
            if (!player)
                return;

            BaseEventPlayer eventPlayer = GetUser(player);
            if (eventPlayer)
                eventPlayer.Event.OnEntityDeployed(baseCombatEntity);
        }

        private object OnCreateWorldProjectile(HitInfo hitInfo, Item item)
        {
            if (hitInfo == null)
                return null;

            if (hitInfo.InitiatorPlayer != null)
            {
                BaseEventPlayer eventPlayer = GetUser(hitInfo.InitiatorPlayer);
                if (eventPlayer)
                    return false;
            }

            if (hitInfo.HitEntity?.ToPlayer() != null)
            {
                BaseEventPlayer eventPlayer = GetUser(hitInfo.HitEntity.ToPlayer());
                if (eventPlayer)
                    return false;
            }

            return null;
        }

        private void OnItemDropped(Item item, WorldItem worldItem)
        {
            BasePlayer player = item.GetOwnerPlayer();
            if (player != null)
            {
                BaseEventPlayer eventPlayer = GetUser(player);
                if (eventPlayer)
                {
                    eventPlayer.Event.OnWorldItemDropped(worldItem);
                }
            }
        }
        #endregion

        #region Items
        private object CanDropActiveItem(BasePlayer player)
        {
            BaseEventPlayer eventPlayer = GetUser(player);
            if (eventPlayer && (!eventPlayer.Event.CanDropActiveItem() || player.health <= 0f))
                return false;
            return null;
        }

        private string CanOpenBackpack(BasePlayer player, ulong backpackOwnerID)
        {
            BaseEventPlayer eventPlayer = GetUser(player);
            if (eventPlayer)
                return "You can not open your backpack during an event";
            return null;
        }                
        #endregion

        #region Command Blacklist
        private object OnPlayerCommand(BasePlayer player, string command, string[] args)
        {
            BaseEventPlayer eventPlayer = GetUser(player);

            if (!player || player.IsAdmin || !eventPlayer)
                return null;

            if (Configuration.Event.CommandBlacklist.Any(x => x.StartsWith("/") ? x.Substring(1).Equals(command, StringComparison.OrdinalIgnoreCase) : x.Equals(command, StringComparison.OrdinalIgnoreCase)))
            {
                SendReply(player, Message("Error.CommandBlacklisted", player.userID));
                return false;
            }
            return null;
        }

        private object OnServerCommand(ConsoleSystem.Arg arg)
        {
            BasePlayer player = arg.Player();
            if (!player || !player.IsConnected)
                return null;

            if (Lobby.ForceLobbyRespawn && (player.IsDead() || player.IsSpectating()))
            {
                if (arg.cmd.Name == RESPAWN_CMD)
                {
                    Lobby.RespawnAtLobby(player);
                    return false;
                }

                if (arg.cmd.Name == REMOVE_BAG_CMD)
                {
                    uint num = arg.GetUInt(0, 0);
                    if (num == LOBBY_BAG_ID)
                        return false;
                }

                if (arg.cmd.Name == RESPAWN_BAG_CMD)
                {
                    uint num = arg.GetUInt(0, 0);
                    if (num == LOBBY_BAG_ID)
                    {
                        Lobby.RespawnAtLobby(player);
                        return false;
                    }
                }
            }

            BaseEventPlayer eventPlayer = GetUser(player);

            if (player.IsAdmin || !eventPlayer || arg.Args == null)
                return null;

            if (Configuration.Event.CommandBlacklist.Any(x => arg.cmd.FullName.Equals(x, StringComparison.OrdinalIgnoreCase)))
            {
                SendReply(player, Message("Error.CommandBlacklisted", player.userID));
                return false;
            }
            return null;
        }
        #endregion

        #region Chat Handler
        private object OnPlayerChat(BasePlayer player, string message, ConVar.Chat.ChatChannel channel)
        {
            if (!player || player.IsAdmin || permission.UserHasPermission(player.UserIDString, "arena.admin"))
                return null;

            BaseEventPlayer eventPlayer = GetUser(player);
            if (eventPlayer)
            {
                eventPlayer.Event.BroadcastToPlayers(player, message);
            }
            else
            {
                foreach (BasePlayer otherPlayer in BasePlayer.activePlayerList)
                {
                    if (!GetUser(otherPlayer))
                        otherPlayer.SendConsoleCommand("chat.add", new object[] { 0, player.UserIDString, $"<color={(player.IsAdmin ? "#aaff55" : player.IsDeveloper ? "#fa5" : "#55AAFF")}>{player.displayName}</color>: {message}" });
                }
            }
               
            return false;
        }
        #endregion

        #region Teams
        private object OnTeamLeave(RelationshipManager.PlayerTeam playerTeam, BasePlayer player)
        {
            BaseEventPlayer eventPlayer = GetUser(player);
            if (!eventPlayer)
                return null;
            
            if (eventPlayer.Event.Plugin.IsTeamEvent)            
                return true;
            
            return null;
        }

        private object OnTeamDisband(RelationshipManager.PlayerTeam playerTeam)
        {
            foreach (BaseEventGame baseEventGame in ActiveEvents.Values)
            {
                if (baseEventGame.IsEventTeam(playerTeam.teamID))
                    return true;                
            }
            return null;
        }

        private object OnTeamInvite(BasePlayer player, BasePlayer other)
        {
            BaseEventPlayer eventPlayer = GetUser(player);
            if (eventPlayer)
                return true;
            return null;
        }

        private object OnTeamCreate(BasePlayer player)
        {
            BaseEventPlayer eventPlayer = GetUser(player);
            if (eventPlayer)
                return true;
            return null;
        }
        #endregion

        #region Event Construction
        public static void RegisterEvent(string eventName, IEventPlugin plugin) => Instance.EventModes[eventName] = plugin;
        
        public static void UnregisterEvent(string eventName)
        {
            Instance.EventModes.Remove(eventName);

            for (int i = Instance.ActiveEvents.Count - 1; i >= 0; i--)
            {
                KeyValuePair<string, BaseEventGame> kvp = Instance.ActiveEvents.ElementAt(i);

                if (kvp.Value.Config.EventType.Equals(eventName))
                {
                    kvp.Value.EndEvent();
                    UnityEngine.Object.Destroy(kvp.Value);
                    Instance.ActiveEvents.Remove(kvp.Key);
                }
            }
        }

        private void InitializeEvents()
        {
            foreach (string eventName in Events.events.Keys)
            {
                object success = OpenEvent(eventName);
                if (success is string)
                    Debug.LogWarning($"[Arena] - {(string)success}");
            }            
        }

        public object OpenEvent(string eventName)
        {
            EventConfig eventConfig;

            if (Events.events.TryGetValue(eventName, out eventConfig))
            {
                if (!string.IsNullOrEmpty(eventConfig.Permission) && !permission.PermissionExists(eventConfig.Permission))
                    permission.RegisterPermission(eventConfig.Permission, this);

                if (eventConfig.IsDisabled)
                    return $"The event {eventName} is disabled";

                IEventPlugin iEventPlugin;
                if (!EventModes.TryGetValue(eventConfig.EventType, out iEventPlugin) || iEventPlugin == null)
                    return $"Unable to find event plugin for game mode: {eventConfig.EventType}";

                object success = ValidateEventConfig(eventConfig);
                if (success is string)
                    return $"Failed to open event {eventName} : {(string)success}";

                if (!iEventPlugin.InitializeEvent(eventConfig))
                    return $"The event {eventName} is already active";
                return null;
            }
            else return "Failed to find a event with the specified name";
        }        

        public static bool InitializeEvent<T>(IEventPlugin plugin, EventConfig config) where T : BaseEventGame
        {
            if (Instance.ActiveEvents.ContainsKey(config.EventName))
                return false;

            BaseEventGame eventGame = new GameObject(config.EventName).AddComponent<T>();
            eventGame.InitializeEvent(plugin, config);

            Instance.ActiveEvents[config.EventName] = eventGame;
            return true;
        }

        public static void ShutdownEvent(string eventName)
        {            
            BaseEventGame baseEventGame;
            if (Instance.ActiveEvents.TryGetValue(eventName, out baseEventGame))
            {
                Instance.ActiveEvents.Remove(eventName);
                UnityEngine.Object.Destroy(baseEventGame);
            }
        }
        #endregion

        #region Functions
        public BaseEventGame FindEvent(string name)
        {
            BaseEventGame baseEventGame;
            ActiveEvents.TryGetValue(name, out baseEventGame);
            return baseEventGame;
        }

        public IEventPlugin GetPlugin(string name)
        {
            IEventPlugin eventPlugin;
            if (EventModes.TryGetValue(name, out eventPlugin))
                return eventPlugin;

            return null;
        }

        private bool CheckDependencies()
        {
            if (!Spawns)
            {
                PrintError("Unable to load Arena - Spawns database not found.Please download Spawns database to continue");
                rust.RunServerCommand("oxide.unload", "Arena");
                return false;
            }

            if (!ZoneManager)
                PrintError("ZoneManager is not installed! Unable to restrict event players to zones");

            if (!Kits)
                PrintError("Kits is not installed! Unable to issue any weapon kits");

            return true;
        }

        internal void TeleportPlayer(BasePlayer player, string spawnFile, bool sleep = false)
        {
            ResetMetabolism(player);

            object spawnPoint = Spawns?.Call("GetRandomSpawn", spawnFile);
            if (spawnPoint is Vector3)            
                TeleportPlayer(player, (Vector3)spawnPoint, sleep);            
        }

        private static void Broadcast(string key, params object[] args)
        {
            foreach (BasePlayer player in BasePlayer.activePlayerList)
                player?.SendConsoleCommand("chat.add", 0, Configuration.Message.ChatIcon, string.Format(Message(key, player.userID), args)); 
        }

        internal static void GetEventsOfType(string eventType, List<BaseEventGame> list)
        {
            foreach (BaseEventGame eventGame in Instance.ActiveEvents.Values)
            {
                if (eventGame.Config.EventType.Equals(eventType, StringComparison.OrdinalIgnoreCase))
                    list.Add(eventGame);
            }
        }

        internal static bool HasActiveEventsOfType(string eventType)
        {
            foreach (BaseEventGame eventGame in Instance.ActiveEvents.Values)
            {
                if (eventGame.Config.EventType.Equals(eventType, StringComparison.OrdinalIgnoreCase))
                    return true;
            }
            return false;
        }

        internal static void GetRegisteredEvents(List<IEventPlugin> list)
        {
            list.AddRange(Instance.EventModes.Values);
            list.Sort((IEventPlugin a, IEventPlugin b) =>
            {
                return a.EventName.CompareTo(b.EventName);
            });
        }
        internal static bool IsValidHex(string s) => hexFilter.IsMatch(s);
        #endregion

        #region Classes and Components  
        public abstract class BaseEventGame : MonoBehaviour
        {
            internal IEventPlugin Plugin { get; private set; }

            internal EventConfig Config { get; private set; }

            public EventStatus Status { get; protected set; }

            protected GameTimer Timer { get; set; }

            internal RewardType RewardType { get; private set; }



            protected CuiElementContainer scoreContainer = null;


            internal List<BaseEventPlayer> eventPlayers = Pool.GetList<BaseEventPlayer>();

            internal List<BaseEventPlayer> joiningSpectators = Pool.GetList<BaseEventPlayer>();


            internal List<ScoreEntry> scoreData = Pool.GetList<ScoreEntry>();

            private List<BaseCombatEntity> _deployedObjects = Pool.GetList<BaseCombatEntity>();

            private List<DroppedItemContainer> _droppedInventories = Pool.GetList<DroppedItemContainer>();

            private List<WorldItem> _droppedItems = Pool.GetList<WorldItem>();

            private List<PlayerCorpse> _droppedCorpses = Pool.GetList<PlayerCorpse>();


            private readonly Hash<string, List<KeyValuePair<string, ulong>>> _kitBeltItems = new Hash<string, List<KeyValuePair<string, ulong>>>();

            protected readonly HashSet<BaseEventPlayer> spectateTargets = new HashSet<BaseEventPlayer>();

            internal HashSet<BaseEventPlayer> SpectateTargets { get { return spectateTargets; } }


            private EventTeleporter _eventTeleporter;

            private bool _isClosed = false;

            protected int _roundNumber = 0;

            internal int RoundNumber => _roundNumber;

            internal EventTeam TeamA { get; private set; }

            internal EventTeam TeamB { get; private set; }

            
            public bool GodmodeEnabled { get; protected set; } = true;

            public EventResults LastEventResult { get; private set; } = new EventResults();

            internal string EventInformation
            {
                get
                {
                    string str = string.Format(Message("Info.Event.Current"), Config.EventName, Config.EventType);
                    str += string.Format(Message("Info.Event.Player"), eventPlayers.Count, Config.MaximumPlayers);
                    return str;
                }
            }

            internal string EventStatus => string.Format(Message("Info.Event.Status"), Status);

            #region Initialization and Destruction             
            protected virtual void OnDestroy()
            {
                CleanupEntities();

                StopAllSpectating();

                for (int i = eventPlayers.Count - 1; i >= 0; i--)
                {
                    BaseEventPlayer eventPlayer = eventPlayers[i];
                    LeaveEvent(eventPlayer);
                }

                for (int i = joiningSpectators.Count - 1; i >= 0; i--)
                {
                    BaseEventPlayer eventPlayer = joiningSpectators[i];
                    LeaveEvent(eventPlayer);
                }

                Pool.FreeList(ref scoreData);
                Pool.FreeList(ref _deployedObjects);
                Pool.FreeList(ref _droppedItems);
                Pool.FreeList(ref _droppedInventories);
                Pool.FreeList(ref _droppedCorpses);
                Pool.FreeList(ref eventPlayers);
                Pool.FreeList(ref joiningSpectators);

                spectateTargets.Clear();

                TeamA?.Destroy();
                TeamB?.Destroy();

                Timer?.StopTimer();

                DestroyTeleporter();

                Destroy(gameObject);
            }

            internal virtual void InitializeEvent(IEventPlugin plugin, EventConfig config)
            {
                this.Config = config;
                this.Plugin = this.Config.Plugin = plugin;

                TeamA = new EventTeam(Team.A, config.TeamConfigA.Color, config.TeamConfigA.Clothing, new SpawnSelector(config.TeamConfigA.Spawnfile));

                if (plugin.IsTeamEvent)
                    TeamB = new EventTeam(Team.B, config.TeamConfigB.Color, config.TeamConfigB.Clothing, new SpawnSelector(config.TeamConfigB.Spawnfile));
                    
                Timer = new GameTimer(this);

                GodmodeEnabled = true;

                RewardType = ParseType<RewardType>(Config.Rewards.Type);

                Status = Arena.EventStatus.Open;

                CreateTeleporter();
            }

            internal List<KeyValuePair<string, ulong>> GetItemsForKit(string kit)
            {
                List<KeyValuePair<string, ulong>> list;
                if (!_kitBeltItems.TryGetValue(kit, out list))
                {
                    JObject obj = Instance.Kits?.Call<JObject>("GetKitObject", kit);
                    if (obj == null)
                    {
                        Debug.LogError($"[Arena] - Kits failed to return data for kit : {kit}.Is this a valid kit name?");
                        return null;
                    }

                    list = _kitBeltItems[kit] = new List<KeyValuePair<string, ulong>>();

                    JArray jArray = obj["BeltItems"] as JArray;

                    foreach (JObject itemObj in jArray)
                        list.Add(new KeyValuePair<string, ulong>((string)itemObj["Shortname"], (ulong)itemObj["SkinID"]));

                }
                return list;
            }
            #endregion

            #region Event Management           
            
            internal virtual void CloseEvent()
            {
                _isClosed = true;
                BroadcastToPlayers("Notification.EventClosed");
            }
                        
            protected virtual void StartEvent()
            {
                if (joiningSpectators.Count > 0)
                {
                    joiningSpectators.ForEach((BaseEventPlayer eventPlayer) => eventPlayers.Add(eventPlayer));
                    joiningSpectators.Clear();
                }

                if (!HasMinimumRequiredPlayers())
                {
                    BroadcastToPlayers("Notification.NotEnoughToStart");
                    EndEvent();
                    return;
                }

                //if (Config.UseEventBots && Config.MaximumBots > 0 && eventPlayers.Count < Config.MaximumPlayers)                
                //    SpawnEventBots();

                _roundNumber = 0;

                LastEventResult.UpdateFromEvent(this);

                Timer.StopTimer();

                UpdateScoreboard();

                Status = Arena.EventStatus.Started;

                StartNextRound();

                SetZoneOccupied(this, true);
            }
                       
            protected virtual void StartNextRound()
            {
                if (!HasMinimumRequiredPlayers())
                {
                    BroadcastToPlayers("Notification.NotEnoughToContinue");
                    EndEvent();
                    return;
                }

                CleanupEntities();

                _roundNumber += 1;

                if (Config.TimeLimit > 0)
                    Timer.StartTimer(Config.TimeLimit, string.Empty, EndRound);

                GodmodeEnabled = false;

                if (CanEnterBetweenRounds())
                {
                    joiningSpectators.ForEach((BaseEventPlayer eventPlayer) => eventPlayers.Add(eventPlayer));
                    joiningSpectators.Clear();
                }

                //if (Config.UseEventBots && Config.MaximumBots > 0)
                //{
                //    if (eventPlayers.Count > Config.MaximumPlayers)
                //        RemoveExcessBots();
                //    else if (eventPlayers.Count < Config.MaximumPlayers)
                //        SpawnEventBots();
                //}

                eventPlayers.ForEach((BaseEventPlayer eventPlayer) =>
                {
                    if (!eventPlayer || !eventPlayer.Player)
                        return;

                    if (CanRespawnPlayer(eventPlayer))
                    {
                        if (eventPlayer.IsDead)
                            RespawnPlayer(eventPlayer);
                        else
                        {
                            ResetPlayer(eventPlayer.Player);
                            OnPlayerRespawn(eventPlayer);
                        }
                    }
                });

                RebuildSpectateTargets();
                UpdateSpectatorTargets();

                UpdateScoreboard();
            }

            protected virtual bool CanRespawnPlayer(BaseEventPlayer baseEventPlayer) => true;

            protected virtual void EndRound()
            {
                UpdateScoreboard();

                if (_roundNumber >= Config.RoundsToPlay)
                {
                    BroadcastToPlayers("Notification.EventFinished");
                    InvokeHandler.Invoke(this, EndEvent, 1f);
                }
                else
                {
                    GodmodeEnabled = true;

                    Timer.StopTimer();

                    LastEventResult.UpdateFromEvent(this);

                    if (Plugin.ProcessWinnersBetweenRounds)
                        ProcessWinners();
                                       
                    eventPlayers.ForEach((BaseEventPlayer eventPlayer) =>
                    {
                        if (!eventPlayer || !eventPlayer.Player)
                            return;

                        eventPlayer.ResetStatistics();

                        if (!CanRespawnPlayer(eventPlayer))
                            return;

                        if (eventPlayer.IsDead)
                        {
                            eventPlayer.OnRoundFinished();
                            RespawnPlayer(eventPlayer);
                        }

                        ArenaStatistics.Data.OnGamePlayed(eventPlayer.Player, Config.EventType);
                    });

                    ArenaStatistics.Data.OnGamePlayed(Config.EventType);

                    if (CanEnterBetweenRounds())
                    {
                        joiningSpectators.ForEach((BaseEventPlayer eventPlayer) =>
                        {
                            eventPlayers.Add(eventPlayer);
                            ResetPlayer(eventPlayer.Player);
                            OnPlayerRespawn(eventPlayer);
                        });

                        joiningSpectators.Clear();
                    }

                    RebuildSpectateTargets();
                    UpdateSpectatorTargets();

                    BroadcastToPlayers("Notification.NextRoundStartsIn", _roundNumber, Configuration.Timer.RoundInterval);
                    Timer.StartTimer(Configuration.Timer.RoundInterval, Message("Timer.NextRoundStartsIn"), StartNextRound);
                }
            }

            internal virtual void EndEvent()
            {
                Timer.StopTimer();

                bool wasPlaying = Status == Arena.EventStatus.Started;
                
                Status = Arena.EventStatus.Finished;

                GodmodeEnabled = true;

                LastEventResult.UpdateFromEvent(this);

                CleanupEntities();

                SetZoneOccupied(this, true);

                if (!IsUnloading && wasPlaying)
                    ProcessWinners();

                StopAllSpectating();

                eventPlayers.ForEach((BaseEventPlayer eventPlayer) =>
                {
                    if (!eventPlayer || !eventPlayer.Player)                    
                        return;
                    
                    eventPlayer.ResetStatistics();

                    if (eventPlayer is NPCEventPlayer)
                    {
                        eventPlayer.Player.Kill(BaseNetworkable.DestroyMode.None);
                        return;
                    }

                    if (eventPlayer.IsDead)
                        RespawnPlayer(eventPlayer);

                    if (!IsUnloading)
                        ArenaStatistics.Data.OnGamePlayed(eventPlayer.Player, Config.EventType);
                });

                if (!IsUnloading)
                {
                    ArenaStatistics.Data.OnGamePlayed(Config.EventType);

                    if (Configuration.Event.StartOnFinish)
                    {
                        BroadcastToPlayers("Notification.NextEventStartsIn", Configuration.Timer.RoundInterval);
                        Timer.StartTimer(Configuration.Timer.RoundInterval, Message("UI.NextGameStartsIn"), StartEvent);
                    }
                    else
                    {
                        EjectAllPlayers();

                        if (joiningSpectators.Count > 0)                        
                            InsertJoiningSpectators();
                    }

                    RebuildSpectateTargets();
                }
            }
            #endregion

            #region Player Management            
            internal bool CanJoinEvent(BasePlayer player)
            {                
                if ((GetActualPlayerCount() + joiningSpectators.Count) >= Config.MaximumPlayers)
                {
                    player.ChatMessage(Message("Notification.MaximumPlayers", player.userID));
                    return false;
                }

                if (!string.IsNullOrEmpty(Config.Permission) && !Instance.permission.UserHasPermission(player.UserIDString, Config.Permission))
                {
                    player.ChatMessage(Message("Error.NoPermission", player.userID));
                    return false;
                }

                string str = CanJoinEvent();
                if (!string.IsNullOrEmpty(str))
                {
                    player.ChatMessage(str);
                    return false;
                }

                return true;
            }

            protected virtual string CanJoinEvent()
            {
                return string.Empty;
            }

            protected virtual bool CanEnterBetweenRounds() => true;

            protected virtual bool CanEnterDuringRound() => !_isClosed;

            internal virtual void JoinEvent(BasePlayer player, Team team = Team.None)
            {
                if (Status == Arena.EventStatus.Started && !CanEnterDuringRound())                
                    CreateSpectatorPlayer(player, team);
                else CreateEventPlayer(player, team);
                
                if (Configuration.Message.BroadcastJoinersGlobal)
                    BroadcastToServer("Notification.PlayerJoined", player.displayName, Config.EventName);

                if (Configuration.Message.BroadcastJoiners)
                    BroadcastToPlayers("Notification.PlayerJoined", player.displayName, Config.EventName);

                if ((Status == Arena.EventStatus.Open || Status == Arena.EventStatus.Finished))
                {
                    if (HasMinimumRequiredPlayers())
                    {
                        Status = Arena.EventStatus.Prestarting;
                        Timer.StartTimer(Configuration.Timer.Prestart, Message("Notification.RoundStartsIn"), StartEvent);
                    }
                    else BroadcastToPlayers("Notification.WaitingForPlayers", Config.MinimumPlayers - eventPlayers.Count);
                }
            }
                        
            internal virtual void LeaveEvent(BasePlayer player)
            {                
                BaseEventPlayer eventPlayer = GetUser(player);
                if (!eventPlayer)
                    return;

                if (eventPlayer is NPCEventPlayer)
                {
                    LeaveEvent(eventPlayer as NPCEventPlayer);
                }
                else
                {
                    LeaveEvent(eventPlayer);

                    if (Configuration.Message.BroadcastLeaversGlobal)
                        BroadcastToServer("Notification.PlayerLeft", player.displayName, Config.EventName);
                    
                    if (Configuration.Message.BroadcastLeavers)
                        BroadcastToPlayers("Notification.PlayerLeft", player.displayName, Config.EventName);
                }
            }

            internal void LeaveEvent(NPCEventPlayer eventPlayer)
            {
                eventPlayers.Remove(eventPlayer);

                StripInventory(eventPlayer.Player);

                DestroyImmediate(eventPlayer);
            }

            internal virtual void LeaveEvent(BaseEventPlayer eventPlayer)
            {
                BasePlayer player = eventPlayer.Player;

                if (eventPlayer.IsDead || player.IsSpectating())
                {
                    ResetPlayer(eventPlayer.Player);
                    TeleportPlayer(player, eventPlayer.Team == Team.B ? TeamB.Spawns.GetSpawnPoint() : TeamA.Spawns.GetSpawnPoint(), false);
                }

                StripInventory(player);

                ResetMetabolism(player);

                if (!string.IsNullOrEmpty(Config.ZoneID))
                    Instance?.ZoneManager?.Call("RemovePlayerFromZoneWhitelist", Config.ZoneID, player);

                if (Plugin.IsTeamEvent && Plugin.CanUseRustTeams && Configuration.Event.AddToTeams)
                {
                    EventTeam eventTeam = eventPlayer.Team == Team.A ? TeamA : TeamB;
                    eventTeam.RemoveFromTeam(player);
                }

                eventPlayers.Remove(eventPlayer);
                joiningSpectators.Remove(eventPlayer);

                RebuildSpectateTargets();

                UpdateSpectatorTargets(eventPlayer);

                DestroyImmediate(eventPlayer);                

                if (!player.IsConnected || player.IsSleeping() || IsUnloading)
                    player.Die();
                else
                {
                    if (Configuration.Server.RestorePlayers)
                        Instance?.Restore.RestorePlayer(player);
                }

                if (Status != Arena.EventStatus.Finished && (!HasMinimumRequiredPlayers() || GetActualPlayerCount() == 0))
                {
                    BroadcastToPlayers("Notification.NotEnoughToContinue");
                    EndEvent();
                }
            }

            internal void InsertJoiningSpectators()
            {
                joiningSpectators.ForEach((BaseEventPlayer eventPlayer) =>
                {
                    eventPlayers.Add(eventPlayer);

                    if (Configuration.Message.BroadcastJoinersGlobal)
                        BroadcastToServer("Notification.PlayerJoined", eventPlayer.Player.displayName, Config.EventName);
                    
                    if (Configuration.Message.BroadcastJoiners)
                        BroadcastToPlayers("Notification.PlayerJoined", eventPlayer.Player.displayName, Config.EventName);

                    if (eventPlayer.Player.IsSpectating())
                    {
                        ResetPlayer(eventPlayer.Player);
                        OnPlayerRespawn(eventPlayer);
                    }
                });

                joiningSpectators.Clear();

                if (HasMinimumRequiredPlayers())
                {
                    Status = Arena.EventStatus.Prestarting;
                    Timer.StartTimer(Configuration.Timer.Prestart, Message("Notification.RoundStartsIn"), StartEvent);
                }
            }

            protected virtual void CreateEventPlayer(BasePlayer player, Team team = Team.None)
            {
                if (!player)
                    return;

                BaseEventPlayer eventPlayer = AddPlayerComponent(player);

                eventPlayer.ResetPlayer();

                eventPlayer.Event = this;

                eventPlayer.Team = team;

                if (Plugin.IsTeamEvent && Plugin.CanUseRustTeams && Configuration.Event.AddToTeams)
                {
                    EventTeam eventTeam = team == Team.A ? TeamA : TeamB;

                    eventTeam.AddToTeam(player);                    
                }

                eventPlayers.Add(eventPlayer);

                if (!Config.AllowClassSelection || GetAvailableKits(eventPlayer.Team).Count == 1)
                    eventPlayer.Kit = GetAvailableKits(eventPlayer.Team).First();

                SpawnPlayer(eventPlayer, Configuration.Event.GiveKitsWhileWaiting || Status == Arena.EventStatus.Started, true);

                if (!string.IsNullOrEmpty(Config.ZoneID))
                    Instance.ZoneManager?.Call("AddPlayerToZoneWhitelist", Config.ZoneID, player);
            }

            protected virtual Team GetSpectatingTeam(Team currentTeam) => currentTeam == Team.A ? Team.A : Team.B;

            protected virtual void CreateSpectatorPlayer(BasePlayer player, Team team = Team.None)
            {
                if (!player)
                    return;

                BaseEventPlayer eventPlayer = AddPlayerComponent(player);

                eventPlayer.ResetPlayer();

                eventPlayer.Event = this;

                eventPlayer.Team = team;

                if (Plugin.IsTeamEvent && Plugin.CanUseRustTeams && Configuration.Event.AddToTeams)
                {
                    EventTeam eventTeam = GetSpectatingTeam(team) == Team.A ? TeamA : TeamB;

                    eventTeam.AddToTeam(player);
                }

                joiningSpectators.Add(eventPlayer);

                if (!Config.AllowClassSelection || GetAvailableKits(eventPlayer.Team).Count == 1)
                    eventPlayer.Kit = GetAvailableKits(team).First();

                eventPlayer.Player.GetMounted()?.AttemptDismount(eventPlayer.Player);

                if (eventPlayer.Player.HasParent())
                    eventPlayer.Player.SetParent(null, true, true);

                StripInventory(player);

                ResetMetabolism(player);

                TeleportPlayer(player, eventPlayer.Team == Team.B ? TeamB.Spawns.GetSpawnPoint() : TeamA.Spawns.GetSpawnPoint(), false);

                if (!string.IsNullOrEmpty(Config.ZoneID))
                    Instance.ZoneManager?.Call("AddPlayerToZoneWhitelist", Config.ZoneID, player);

                eventPlayer.BeginSpectating();

                UpdateScoreboard(eventPlayer);
                 
                BroadcastToPlayer(eventPlayer, Message("Notification.JoinerSpectate", player.userID));

                ArenaUI.ShowHelpText(eventPlayer);
            }

            protected virtual Team GetPlayerTeam() => Team.None;

            protected virtual BaseEventPlayer AddPlayerComponent(BasePlayer player) => player.gameObject.GetComponent<BaseEventPlayer>() ?? player.gameObject.AddComponent<BaseEventPlayer>();

            internal virtual void OnPlayerRespawn(BaseEventPlayer baseEventPlayer)
            {
                SpawnPlayer(baseEventPlayer, Configuration.Event.GiveKitsWhileWaiting || Status == Arena.EventStatus.Started);
            }

            internal void SpawnPlayer(BaseEventPlayer eventPlayer, bool giveKit = true, bool sleep = false)
            {
                if (!eventPlayer|| !eventPlayer.Player)
                    return;

                if (eventPlayer.Player.IsSpectating())
                    eventPlayer.FinishSpectating();

                eventPlayer.Player.GetMounted()?.AttemptDismount(eventPlayer.Player);
                                
                if (eventPlayer.Player.HasParent())
                    eventPlayer.Player.SetParent(null, true);

                StripInventory(eventPlayer.Player);

                ResetMetabolism(eventPlayer.Player);

                TeleportPlayer(eventPlayer.Player, eventPlayer.Team == Team.B ? TeamB.Spawns.GetSpawnPoint() : TeamA.Spawns.GetSpawnPoint(), sleep);

                if (string.IsNullOrEmpty(eventPlayer.Kit) && !(eventPlayer is NPCEventPlayer))
                {
                    eventPlayer.ForceSelectClass();
                    ArenaUI.DisplayDeathScreen(eventPlayer, Message("UI.SelectClass", eventPlayer.Player.userID), true);
                    return;
                }

                UpdateScoreboard(eventPlayer);

                if (giveKit)
                {
                    Instance.NextTick(() =>
                    {
                        if (eventPlayer && CanGiveKit(eventPlayer))
                        {
                            GiveKit(eventPlayer.Player, eventPlayer.Kit);
                            OnKitGiven(eventPlayer);
                        }
                    });
                }

                eventPlayer.ApplyInvincibility();

                OnPlayerSpawned(eventPlayer);

                RebuildSpectateTargets();

                UpdateSpectatorTargets();

                ArenaUI.ShowHelpText(eventPla
// ... [Code preview truncated due to length. Full source in attached file] ...

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

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

Сверху