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

FREE EventHelper : 1.0.20 1.0.20

Нет прав для скачивания
C#:
using Facepunch;
using HarmonyLib;
using Newtonsoft.Json;
using Oxide.Core;
using Oxide.Core.Configuration;
using Oxide.Core.Plugins;
using Rust;
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using static RelationshipManager;
/* 
 * 
 */
/* 1.0.20
 * Updated for August forced wipe
 */
namespace Oxide.Plugins {
    [Info("EventHelper", "imthenewguy", "1.0.20")]
    [Description("A plugin that devs can use to help get players into events.")]
    class EventHelper : RustPlugin {
#region Config
        private Configuration config;
        public class Configuration {
            [JsonProperty("A list of items that cannot be taken into an event")]
            public List<string> black_listed_items = new List<string>() {
                "cassette", "	cassette.medium", "cassette.short", "fun.casetterecorder", "boombox"
            }
            ;
            [JsonProperty("The command to recover items")]
            public string redeem_items_command = "recoveritems";
            [JsonProperty("How often should we cycle through events")]
            public float event_cycle_timer = 7200f;
            [JsonProperty("Set to true if the server is giving players a kit on respawn and you want players to receive their saved items back automatically")]
            public bool auto_rekit = false;
            [JsonProperty("Unban players on server wipe?")]
            public bool unban_players = true;
            [JsonProperty("Allow players to vote for games manually?")]
            public bool voting_enabled = true;
            [JsonProperty("Command to initiate a vote for an event")]
            public string vote_start_cmd = "eventvote";
            [JsonProperty("Command to vote for an event")]
            public string vote_cmd = "vote";
            [JsonProperty("Max vote time (seconds)")]
            public int max_vote_time = 300;
            [JsonProperty("Percentage of players required for a vote to pass [1.0 = 100% of players]")]
            public float vote_percentage = 0.3f;
            [JsonProperty("Minimum temperature while at an event")]
            public float temperature_min = 25f;
            [JsonProperty("Maximum temperature while at an event")]
            public float temperature_max = 25f;
            [JsonProperty("How often should players be reminded of the voting feature (seconds)? [0 = off]")]
            public float voting_reminder_time = 1200f;
            [JsonProperty("Minimum online players before voting is allowed? [0 = no limit]")]
            public int minimum_players_online_vote = 0;
            [JsonProperty("Minimum online players before automatic arenas start? [0 = no limit]")]
            public int minimum_players_online_auto_start = 0;
            [JsonProperty("Remove entities that are stuck to the player on entry to the event?")]
            public bool clear_stuck_entities = true;
            [JsonProperty("Prevent players who are flagged with the NoEscape plugin from joining the event?")]
            public bool prevent_no_escape_joins = true;
            [JsonProperty("Announce in chat when a player joins an event?")]
            public bool announce_player_join = true;
            [JsonProperty("Settings for Discord plugin")]
            public DiscordSettings discordSettings = new DiscordSettings();
            public string ToJson() => JsonConvert.SerializeObject(this);
            public Dictionary<string, object> ToDictionary() => JsonConvert.DeserializeObject<Dictionary<string, object>>(ToJson());
        }
        public class DiscordSettings {
            [JsonProperty("Webhook URL")]
            public string webhook;
            [JsonProperty("Send a discord notification when an event starts?")]
            public bool send_on_event = true;
        }
        protected override void LoadDefaultConfig() => config = new Configuration();
        protected override void LoadConfig() {
            base.LoadConfig();
            try {
                config = Config.ReadObject<Configuration>();
                if (config == null) {
                    throw new JsonException();
                }
                if (!config.ToDictionary().Keys.SequenceEqual(Config.ToDictionary(x => x.Key, x => x.Value).Keys)) {
                    PrintToConsole("Configuration appears to be outdated; updating and saving");
                    SaveConfig();
                }
            }
            catch {
                PrintToConsole($"Configuration file {Name}.json is invalid; using defaults");
                LoadDefaultConfig();
            }
        }
        protected override void SaveConfig() {
            PrintToConsole($"Configuration changes saved to {Name}.json");
            Config.WriteObject(config, true);
        }
#endregion
#region classes
        public Dictionary<string, EventInfo> Events = new Dictionary<string, EventInfo>(StringComparer.OrdinalIgnoreCase);
        public Dictionary<string, bool> EventRunning = new Dictionary<string, bool>(StringComparer.OrdinalIgnoreCase);
        List<ulong> BagPreventDropList = new List<ulong>();
        public class EventInfo {
            public bool automatic_start;
            public bool strip_items;
            public bool leaves_event_on_death;
            public bool full_health_on_join;
            public bool give_items_back_automatically;
            public bool full_metabolism_on_join;
            public bool restricted_temp;
            public Vector3 teleport_destination;
            public List<BasePlayer> participants = new List<BasePlayer>();
            public bool manually_started;
            public bool allow_Teams;
            public string[] black_listed_commands;
            public ExternalPluginSettings external_plugin_settings = new ExternalPluginSettings(false, false, false, false, false, false);
            public EventInfo(bool automatic_start, bool strip_items, bool leaves_event_on_death, bool full_health_on_join, bool give_items_back_automatically, bool full_metabolism_on_join, Vector3 teleport_destination, bool restricted_temp = true, bool allow_Teams = true) {
                this.automatic_start = automatic_start;
                this.strip_items = strip_items;
                this.leaves_event_on_death = leaves_event_on_death;
                this.full_health_on_join = full_health_on_join;
                this.give_items_back_automatically = give_items_back_automatically;
                this.full_metabolism_on_join = full_metabolism_on_join;
                this.teleport_destination = teleport_destination;
                this.restricted_temp = restricted_temp;
                this.allow_Teams = allow_Teams;
            }
            public class ExternalPluginSettings {
                public bool canDropBackpack;
                public bool canEraseBackpack;
                public bool canOpenBackpack;
                public bool canBackpackAcceptItem;
                public bool canRedeemKit;
                public bool CanLoseXP;
                public ExternalPluginSettings(bool canDropBackpack, bool canEraseBackpack, bool canOpenBackpack, bool canBackpackAcceptItem, bool canRedeemKit, bool CanLoseXP) {
                    this.canDropBackpack = canDropBackpack;
                    this.canEraseBackpack = canEraseBackpack;
                    this.canOpenBackpack = canOpenBackpack;
                    this.canBackpackAcceptItem = canBackpackAcceptItem;
                    this.canRedeemKit = canRedeemKit;
                    this.CanLoseXP = CanLoseXP;
                }
            }
        }
        public enum ContainerType {
            Main, Belt, Wear, None
        }
        public class ItemInfo {
            public string shortname;
            public ulong skin;
            public int amount;
            public float condition;
            public float maxCondition;
            public int ammo;
            public string ammotype;
            public ContainerType container;
            public int position;
            public int frequency;
            public Item.Flag flags;
            public KeyInfo instanceData;
            public class KeyInfo {
                public int dataInt;
                public int blueprintTarget;
                public int blueprintAmount;
            }
            public int contentsSlots;
            public List<ItemInfo> item_contents;
            public string text;
            public string name;
            public List<ItemOwnershipShare> ownershipShares;
            public int armorSlots;
        }
#endregion
#region Data
        PlayerEntity pcdData;
        private DynamicConfigFile PCDDATA;
        const string perm_admin = "eventhelper.admin";
        void Init() {
            WasAtEvent = new Dictionary<ulong, string>();
            PCDDATA = Interface.Oxide.DataFileSystem.GetFile(this.Name);
            LoadData();
            permission.RegisterPermission(perm_admin, this);
            cmd.AddChatCommand(config.vote_cmd, this, "VoteForEvent");
            cmd.AddChatCommand(config.vote_start_cmd, this, "StartEventVote");
            Temperature_Min = config.temperature_min;
            Temperature_Max = config.temperature_max;
            if (config.voting_reminder_time > 0 && config.voting_enabled) {
                timer.Every(config.voting_reminder_time, () => {
                    PrintToChat(string.Format(lang.GetMessage("VotingReminder", this), config.vote_start_cmd));
                }
                );
            }
        }
        void Unload() {
            cmd.RemoveChatCommand(config.redeem_items_command, this);
            cmd.RemoveChatCommand(config.vote_cmd, this);
            cmd.RemoveChatCommand(config.vote_start_cmd, this);
            foreach (var kvp in pcdData.pEntity) {
                kvp.Value.AtEvent = false;
                kvp.Value.Event = null;
            }
            foreach (var e in Events.ToList()) {
                EMRemoveEvent(e.Key);
            }
            SaveData();
            foreach (var player in BasePlayer.activePlayerList) {
                DestroyTempRestriction(player);
            }
            WasAtEvent.Clear();
            WasAtEvent = null;
        }
        void SaveData() {
            PCDDATA.WriteObject(pcdData);
        }
        void LoadData() {
            try {
                pcdData = Interface.Oxide.DataFileSystem.ReadObject<PlayerEntity>(this.Name);
            }
            catch {
                Puts(lang.GetMessage("NoPlayerDataLoading", this));
                pcdData = new PlayerEntity();
            }
        }
        class PlayerEntity {
            public Dictionary<ulong, PCDInfo> pEntity = new Dictionary<ulong, PCDInfo>();
            public Dictionary<string, List<ulong>> banned_players = new Dictionary<string, List<ulong>>();
        }
        class PCDInfo {
            public string Event;
            public float Health;
            public string Modifiers;
            public string Metabolism;
            public bool AtEvent;
            public Vector3 Location;
            public List<ItemInfo> Items = new List<ItemInfo>();
            public bool StripOnItemRestore;
            public bool RestoreOnWake;
            [NonSerialized]
            public bool RestoringItems;
        }
        [PluginReference]
        private Plugin Backpacks, NoEscape, RestoreUponDeath;
#endregion;
#region Localization
        protected override void LoadDefaultMessages() {
            lang.RegisterMessages(new Dictionary<string, string> {
                ["AtEvent"]
                = "You are already at an event.", ["ItemsStored"] = "You have items stored that must be claimed before joining another event. Type /{0} to recover your items (doing this will delete your current inventory).", ["NoCrafting"] = "You must stop crafting in order to join this event.", ["EscapeBlocked"] = "You cannot join the game while you are escape blocked.", ["BlackListedItem"] = "You cannot bring a {0} into a minigame.", ["BlackListedItemSub"] = "You cannot bring a {0} into a minigame. This was found inside of your {1}", ["AlreadyEnrolled"] = "You are already enrolled in this event.", ["FailedToStrip"] = "Failed to strip your items.", ["ManualItemRecovery"] = "You must type /{0} to recover them (doing this will delete your current inventory).", ["NoRecovery"] = "You cannot recover your items until you leave the event.", ["NoCommand"] = "You cannot use the {0} command at this event.", ["UnclaimedItems"] = "You have unclaimed items. Type /{0} to recover them.", ["SkipStart"] = "Skipping event start due to manual start.", ["ManualStart"] = "Manually started event {0}", ["RemovedEvent"] = "Removed Event: {0}", ["SetupEvent"] = "Setup Event: {0}", ["EndedEvent"] = "Ended the event", ["NotSetup"] = "{0} has not been setup.", ["EventNotSetupExternalPluginSettings"] = "Event: {0} has not been setup. Must call EMCreateEvent before EMExternalPluginSettings.", ["EventNotSetupBlackList"] = "Event: {0} has not been setup. Must call EMCreateEvent before EMBlackListCommands.", ["RegisteredCommands"] = "Registered {0} black listed commands.", ["NoPlayerDataLoading"] = "Couldn't load player data, creating new Playerfile", ["NoEventData"] = "You have no event data stored.", ["MorePlayersFound"] = "More than one player found: {0}", ["NoMatch"] = "No player was found that matched: {0}", ["EHBanUsage"] = "Usage: /ehban <player name/id>", ["BannedPlayer"] = "Banned {0} from all EventHelper events.", ["EHUnbanUsage"] = "Usage: /ehunban <player name/id>", ["UnbannedPlayer"] = "Unbanned {0} from all EventHelper events.", ["NoBan"] = "{0} does not have any bans.", ["VotingReminder"] = "You can vote to start your favourite event by typing <color=#ffec00>/{0} <event name></color>", ["EventNotRegistered"] = "Failed to join - Event: {0} has not been registered!", ["PreventTeamCreation"] = "The event you are in does not allow team creation.", ["DiscordMessageEventStarted"] = ":globe_with_meridians: Event Started: {0}.", ["JointAnnounceMsg_1"] = "<color=#00fff7>{0}</color> has decided to join the action at the <color=#00ff83>{1}</color> event!", ["JointAnnounceMsg_2"] = "<color=#00fff7>{0}</color> has joined the <color=#00ff83>{1}</color> event and is ready to take some names!", ["JointAnnounceMsg_3"] = "Oh no, <color=#00fff7>{0}</color> has joined the <color=#00ff83>{1}</color> event!",
            }
            , this);
        }
#endregion
#region Methods
        bool IsPlayerBanned(BasePlayer player, string eventName) {
            if (pcdData.banned_players.ContainsKey(eventName) && pcdData.banned_players[eventName].Contains(player.userID)) return true;
            if (pcdData.banned_players.ContainsKey("global") && pcdData.banned_players["global"].Contains(player.userID)) return true;
            return false;
        }
        bool CanJoinEvent(BasePlayer player, string eventName, PCDInfo playerData) {
            if (playerData.RestoringItems) {
                PrintToChat(player, $"You must wait for your items to restore before joining this game.");
                return false;
            }
            if (IsPlayerBanned(player, eventName)) {
                PrintToChat(player, $"You are banned from the event and cannot join.");
                return false;
            }
            if (playerData.AtEvent) {
                PrintToChat(player, lang.GetMessage("AtEvent", this, player.UserIDString));
                return false;
            }
            if (HasItemsStored(player.userID) && !playerData.AtEvent) {
                PrintToChat(player, string.Format(lang.GetMessage("ItemsStored", this, player.UserIDString), config.redeem_items_command));
                return false;
            }
            if (player.inventory.crafting.queue.Count != 0) {
                PrintToChat(player, lang.GetMessage("NoCrafting", this, player.UserIDString));
                return false;
            }
            if (NoEscape != null && config.prevent_no_escape_joins && Convert.ToBoolean(NoEscape.Call("IsEscapeBlocked", player.UserIDString))) {
                PrintToChat(player, lang.GetMessage("EscapeBlocked", this, player.UserIDString));
                return false;
            }
            if (HasProhibitedItems(player)) return false;
            if (Interface.CallHook("EMOnEventJoin", player, eventName) != null) {
                PrintToChat(player, "Another plugin preventing you from joining");
                return false;
            }
            var hook = Interface.CallHook("OnEventJoin", player, eventName);
            if (hook != null) {
                if (hook is string) PrintToChat(player, hook as string);
                else PrintToChat(player, "An external plugin has preventing you from joining the event.");
                return false;
            }
            return true;
        }
        object OnEventJoin(BasePlayer player, string eventName) {
            var playerData = GetPlayer(player.userID, false);
            if (playerData == null) return null;
            if (playerData.AtEvent) return $"You must leave the {playerData.Event} event before attempting to join a new one.";
            return null;
        }
        bool StorePlayerItems(BasePlayer player, PCDInfo playerData) {
            playerData.Items.AddRange(GetItems(player, player.inventory.containerWear));
            playerData.Items.AddRange(GetItems(player, player.inventory.containerMain));
            playerData.Items.AddRange(GetItems(player, player.inventory.containerBelt));
            player.inventory.Strip();
            SaveData();
            return true;
        }
        List<ItemInfo> GetItems(BasePlayer player, ItemContainer container) {
            string messageText = $"\n\n------------\nGetItems for {player.displayName} [{player.userID}]\n";
            List<ItemInfo> result = new List<ItemInfo>();
            foreach (var item in container.itemList) {
                messageText += $"- Adding item: {item.name ?? item.info.shortname}. Container: {(container == player.inventory.containerWear ? "Worn items" : container == player.inventory.containerBelt ? "Belt items" : container == player.inventory.containerMain ? "Main items" : "Item contents")}\n";
                result.Add(new ItemInfo() {
                    shortname = item.info.shortname, position = item.position, container = GetContainer(player, container), amount = item.amount, ammo = item.GetHeldEntity() is BaseProjectile ? (item.GetHeldEntity() as BaseProjectile).primaryMagazine.contents : item.GetHeldEntity() is FlameThrower ? (item.GetHeldEntity() as FlameThrower).ammo : item.GetHeldEntity() is Chainsaw ? (item.GetHeldEntity() as Chainsaw).ammo : 0, ammotype = (item.GetHeldEntity() as BaseProjectile)?.primaryMagazine.ammoType.shortname ?? null, skin = item.skin, condition = item.condition, maxCondition = item.maxCondition, flags = item.flags, instanceData = item.instanceData != null ? new ItemInfo.KeyInfo() {
                        dataInt = item.instanceData.dataInt, blueprintTarget = item.instanceData.blueprintTarget, blueprintAmount = item.instanceData.blueprintAmount,
                    }
                    : null, name = item.name ?? null, text = item.text ?? null, item_contents = item.contents?.itemList != null ? GetItems(player, item.contents) : null, contentsSlots = item.contents?.capacity ?? 0, ownershipShares = item.ownershipShares
                }
                );
            }
            LogToFile("GetItems", messageText, this, true, true);
            return result;
        }
        Item GetRestoreItem(BasePlayer player, ItemContainer container, ItemInfo savedItem) {
            var item = ItemManager.CreateByName(savedItem.shortname, savedItem.amount, savedItem.skin);
            if (savedItem.name != null) item.name = savedItem.name;
            if (savedItem.text != null) item.text = savedItem.text;
            item.condition = savedItem.condition;
            item.maxCondition = savedItem.maxCondition;
            if (savedItem.contentsSlots > 0 && item.info.isWearable && item.info.TryGetComponent<ItemModContainerArmorSlot>(out var aSlots)) {
                aSlots.CreateAtCapacity(savedItem.contentsSlots, item);
            }
            BaseEntity heldEntity = item.GetHeldEntity();
            item.flags = savedItem.flags;
            if (savedItem.instanceData != null) {
                item.instanceData = new ProtoBuf.Item.InstanceData();
                item.instanceData.ShouldPool = false;
                item.instanceData.dataInt = savedItem.instanceData.dataInt;
                item.instanceData.blueprintTarget = savedItem.instanceData.blueprintTarget;
                item.instanceData.blueprintAmount = savedItem.instanceData.blueprintAmount;
            }
            if (savedItem.item_contents != null && savedItem.item_contents.Count > 0) {
                if (item.contents == null) {
                    item.contents = new ItemContainer();
                    item.contents.ServerInitialize(null, savedItem.item_contents.Count);
                    item.contents.GiveUID();
                    item.contents.parent = item;
                }
                foreach (var _item in savedItem.item_contents) {
                    GetRestoreItem(player, item.contents, _item);
                }
            }
            if (savedItem.ownershipShares != null && savedItem.ownershipShares.Count > 0) item.ownershipShares = savedItem.ownershipShares;
            BaseProjectile weapon = heldEntity as BaseProjectile;
            if (weapon != null) {
                weapon.DelayedModsChanged();
                if (!string.IsNullOrEmpty(savedItem.ammotype)) weapon.primaryMagazine.ammoType = ItemManager.FindItemDefinition(savedItem.ammotype);
                weapon.primaryMagazine.contents = savedItem.ammo;
            }
            else if (savedItem.ammo > 0) {
                FlameThrower flameThrower = heldEntity as FlameThrower;
                if (flameThrower != null) flameThrower.ammo = savedItem.ammo;
                else {
                    Chainsaw chainsaw = heldEntity as Chainsaw;
                    if (chainsaw != null) chainsaw.ammo = savedItem.ammo;
                }
            }
            item.MarkDirty();
            if (!item.MoveToContainer(container, savedItem.position)) player.GiveItem(item);
            return item;
        }
        void StorePlayerMods(BasePlayer player, PCDInfo playerData) {
            playerData.Modifiers = SaveModifiers(player);
            player.modifiers.RemoveAll();
            player.modifiers.SendChangesToClient();
        }
        void StorePlayerMetabolism(BasePlayer player, PCDInfo playerData) {
            playerData.Metabolism = SaveMetabolism(player);
            playerData.Health = player.health;
            player.metabolism.Reset();
            player.metabolism.calories.SetValue(player.metabolism.calories.max);
            player.metabolism.hydration.SetValue(player.metabolism.hydration.max);
            player.metabolism.SendChanges();
            player.SetHealth(player.MaxHealth());
        }
        string SaveModifiers(BasePlayer player) {
            ProtoBuf.PlayerModifiers snapshot = player.modifiers.Save(true);
            byte[] bytes = snapshot.ToProtoBytes();
            return Convert.ToBase64String(bytes);
            // encode byte array to utf8 string
        }
        string SaveMetabolism(BasePlayer player) {
            ProtoBuf.PlayerMetabolism snapshot = player.metabolism.Save();
            byte[] bytes = snapshot.ToProtoBytes();
            return Convert.ToBase64String(bytes);
            // encode byte array to utf8 string
        }
        ContainerType GetContainer(BasePlayer player, ItemContainer container) {
            if (container.uid == player.inventory.containerBelt.uid) return ContainerType.Belt;
            else if (container.uid == player.inventory.containerWear.uid) return ContainerType.Wear;
            else if (container.uid == player.inventory.containerMain.uid) return ContainerType.Main;
            else return ContainerType.None;
        }
        bool HasProhibitedItems(BasePlayer player) {
            var items = AllItems(player);
            try {
                if (config.black_listed_items == null || config.black_listed_items.Count == 0 || items.Count == 0) return false;
                foreach (var item in items) {
                    if (config.black_listed_items.Contains(item.info.shortname)) {
                        PrintToChat(player, string.Format(lang.GetMessage("BlackListedItem", this, player.UserIDString), item.info.displayName.english));
                        return true;
                    }
                    if (item.contents != null && item.contents.itemList != null && item.contents.itemList.Count > 1) {
                        foreach (var sub_item in item.contents.itemList) {
                            if (config.black_listed_items.Contains(sub_item.info.shortname)) {
                                PrintToChat(player, string.Format(lang.GetMessage("BlackListedItemSub", this, player.UserIDString), item.info.displayName.english, item.info.displayName.english));
                                return true;
                            }
                        }
                    }
                }
            }
            finally {
                Pool.FreeUnmanaged(ref items);
            }
            return false;
        }
        private bool HasItemsStored(ulong id) {
            var playerData = GetPlayer(id);
            if (playerData.Items.Count == 0) return false;
            return true;
        }
        bool IsPlayerSetup(ulong id) {
            return pcdData.pEntity.ContainsKey(id);
        }
        PCDInfo GetPlayer(ulong id, bool create = true) {
            PCDInfo result;
            if (pcdData.pEntity.TryGetValue(id, out result)) return result;
            if (!create) return null;
            pcdData.pEntity.Add(id, result = new PCDInfo());
            return result;
        }
        void RestoreStats(BasePlayer player, PCDInfo playerData) {
            if (player.IsDead() || !player.IsConnected) return;
            bool madeChange = false;
            if (LoadMetabolism(player, playerData)) madeChange = true;
            if (playerData.Health > 0) {
                player.health = playerData.Health;
                playerData.Health = 0;
                madeChange = true;
            }
            if (playerData.Location != Vector3.zero) {
                TeleportToEvent(player, playerData.Location, false);
                playerData.Location = Vector3.zero;
                madeChange = true;
            }
            if (madeChange) {
                player.State.unHostileTimestamp = Network.TimeEx.currentTimestamp;
                player.MarkHostileFor(0);
            }
            DestroyTempRestriction(player);
        }
        bool LoadMetabolism(BasePlayer player, PCDInfo playerData) {
            if (string.IsNullOrEmpty(playerData.Metabolism)) return false;
            if (player.IsWounded()) player.RecoverFromWounded();
            byte[] bytes = Convert.FromBase64String(playerData.Metabolism);
            ProtoBuf.PlayerMetabolism snapshot = ProtoBuf.PlayerMetabolism.Deserialize(bytes);
            player.metabolism.Load(snapshot);
            playerData.Metabolism = null;
            return true;
        }
        void LoadModifiers(BasePlayer player, PCDInfo playerData) {
            if (string.IsNullOrEmpty(playerData.Modifiers)) return;
            byte[] bytes = Convert.FromBase64String(playerData.Modifiers);
            ProtoBuf.PlayerModifiers snapshot = ProtoBuf.PlayerModifiers.Deserialize(bytes);
            player.modifiers.Load(snapshot, true);
            playerData.Modifiers = null;
        }
        void StorePlayerInfo(BasePlayer player, bool StoreHealth, bool StoreStats, bool StoreTemp) {
            var playerData = GetPlayer(player.userID);
            StorePlayerMods(player, playerData);
            StorePlayerMetabolism(player, playerData);
            player.metabolism.bleeding.SetValue(0);
            player.metabolism.radiation_level.SetValue(0);
            player.metabolism.radiation_poison.SetValue(0);
            player.SetHealth(100f);
            if (StoreTemp) AddTempRestriction(player);
            playerData.Location = player.transform.position;
        }
        void TeleportToEvent(BasePlayer player, Vector3 loc, bool toLobby) {
            if (loc == Vector3.zero) return;
            player.SetParent(null, worldPositionStays : true);
            Player.Teleport(player, loc);
            player.ForceUpdateTriggers();
            player.ClientRPC(RpcTarget.Player("StartLoading_Quick", player), arg1 : true);
            player.UpdateNetworkGroup();
            player.SetPlayerFlag(BasePlayer.PlayerFlags.ReceivingSnapshot, true);
            BasePlayer.ResetAntiHack(player, AntiHack.PlayerStates, AntiHack.PlayerNoclipStates, AntiHack.PlayerSpeedhackStates, AntiHack.PlayerFlyhackStates);
            player.PauseFlyHackDetection(3f);
            player.PauseSpeedHackDetection(3f);
            player.ApplyStallProtection(4f);
            if (!toLobby) player.StartSleeping();
            if (config.clear_stuck_entities) {
                if (player.children != null) {
                    List<BaseEntity> stuck = Pool.Get<List<BaseEntity>>();
                    foreach (var child in player.children) {
                        if (child.PrefabName == "assets/prefabs/misc/burlap sack/generic_world.prefab") {
                            var item = child.GetItem();
                            if (item != null) {
                                var heldEntity = item.GetHeldEntity();
                                if ((heldEntity != null && heldEntity is BaseMelee) || item.info.shortname.StartsWith("arrow.") || item.info.shortname.Equals("ammo.nailgun.nails")) stuck.Add(child);
                            }
                        }
                    }
                    foreach (var child in stuck) {
                        child.KillMessage();
                    }
                    Pool.FreeUnmanaged(ref stuck);
                }
            }
        }
        void RemoveFromEvent(BasePlayer player, string eventName) {
            if (!IsPlayerSetup(player.userID)) return;
            var playerData = GetPlayer(player.userID);
            playerData.AtEvent = false;
            EventInfo ei;
            if (eventName != null) Events.TryGetValue(eventName, out ei);
            else ei = null;
            ei.participants.Remove(player);
        }
        BasePlayer FindPlayerByID(string id, BasePlayer searchingPlayer = null) {
            if (!id.IsSteamId()) return null;
            var player = BasePlayer.allPlayerList.Where(x => x.UserIDString == id).FirstOrDefault();
            if (player == null) {
                if (searchingPlayer != null) PrintToChat(searchingPlayer, string.Format(lang.GetMessage("NoMatch", this), id));
                else Puts(string.Format(lang.GetMessage("NoMatch", this), id));
            }
            return player ?? null;
        }
        private BasePlayer FindPlayerByName(string Playername, BasePlayer SearchingPlayer = null) {
            var lowered = Playername.ToLower();
            var targetList = BasePlayer.allPlayerList.Where(x => x.displayName.ToLower().Contains(lowered)).OrderBy(x => x.displayName.Length);
            if (targetList.Count() == 1) {
                return targetList.First();
            }
            if (targetList.Count() > 1) {
                if (targetList.First().displayName.Equals(Playername, StringComparison.OrdinalIgnoreCase)) {
                    return targetList.First();
                }
                if (SearchingPlayer != null) {
                    PrintToChat(SearchingPlayer, string.Format(lang.GetMessage("MorePlayersFound", this, SearchingPlayer.UserIDString), String.Join(",", targetList.Select(x => x.displayName))));
                }
                else Puts(string.Format(lang.GetMessage("MorePlayersFound", this), String.Join(",", targetList.Select(x => x.displayName))));
                return null;
            }
            if (targetList.Count() == 0) {
                if (SearchingPlayer != null) {
                    PrintToChat(SearchingPlayer, string.Format(lang.GetMessage("NoMatch", this, SearchingPlayer.UserIDString), Playername));
                }
                else Puts(string.Format(lang.GetMessage("NoMatch", this), Playername));
                return null;
            }
            return null;
        }
        public bool AddBan(BasePlayer player, string event_name) {
            if (!pcdData.banned_players.ContainsKey(event_name)) pcdData.banned_players.Add(event_name, new List<ulong>());
            if (!pcdData.banned_players[event_name].Contains(player.userID)) {
                pcdData.banned_players[event_name].Add(player.userID);
                SaveData();
                return true;
            }
            return false;
        }
        public bool RemoveBan(BasePlayer player, string event_name) {
            if (!pcdData.banned_players.ContainsKey(event_name) || !pcdData.banned_players[event_name].Contains(player.userID)) return false;
            pcdData.banned_players[event_name].Remove(player.userID);
            SaveData();
            return true;
        }
#endregion
#region Event Stuff
        string LastEvent;
        List<string> automatic_Events = new List<string>();
        void StartNextEvent() {
            if (config.minimum_players_online_auto_start > 0 && BasePlayer.activePlayerList?.Count < config.minimum_players_online_auto_start) {
                Puts($"Attmempted to start a game, but there are not enough players online [{BasePlayer.activePlayerList?.Count}/{config.minimum_players_online_auto_start}].");
                return;
            }
            if (Events == null || Events.Count == 0 || automatic_Events.Count == 0) return;
            foreach (var _event in Events) if (_event.Value.manually_started) {
                Puts($"Attempted to start a new event, but {_event.Key} is still flagged as manually started.");
                return;
            }
            if (LastEvent != null && Events.ContainsKey(LastEvent) && !Events[LastEvent].manually_started) {
                Interface.CallHook("EMEndGame", LastEvent);
                EMEndEvent(LastEvent);
            }
            if (LastEvent == null) {
                Interface.CallHook("EMStartNextEvent", automatic_Events.First());
                Puts($"Attempting to start: {automatic_Events.First()}. Events: {string.Join(", ", automatic_Events)}");
                LastEvent = automatic_Events.First();
                SendDiscordMsg(string.Format(lang.GetMessage("DiscordMessageEventStarted", this), automatic_Events.First().TitleCase()));
            }
            else {
                var foundLastEvent = false;
                var setNewEvent = false;
                foreach (var e in automatic_Events) {
                    if (Events[e].manually_started) continue;
                    if (foundLastEvent) {
                        Interface.CallHook("EMStartNextEvent", e);
                        Puts($"Attempting to start: {e}. Events: {string.Join(", ", automatic_Events)}");
                        LastEvent = e;
                        setNewEvent = true;
                        SendDiscordMsg(string.Format(lang.GetMessage("DiscordMessageEventStarted", this), e.TitleCase()));
                        break;
                    }
                    else if (e == LastEvent) foundLastEvent = true;
                }
                if (!setNewEvent) {
                    var e = automatic_Events.First();
                    if (!Events[e].manually_started) {
                        Interface.CallHook("EMStartNextEvent", e);
                        Puts($"Attempting to start: {e}. Events: {string.Join(", ", automatic_Events)}");
                        LastEvent = e;
                    }
                    else Puts(lang.GetMessage("SkipStart", this));
                }
            }
        }
        [HookMethod("EMWasManuallyStarted")]
        public bool EMWasManuallyStarted(string eventName) {
            EventInfo ei;
            if (Events.TryGetValue(eventName, out ei)) {
                return ei.manually_started;
            }
            return false;
        }
        [HookMethod("EMManuallyStarted")]
        public void EMManuallyStarted(string eventName) {
            EventInfo ei;
            if (Events.TryGetValue(eventName, out ei)) {
                ei.manually_started = true;
                Puts(string.Format(lang.GetMessage("ManualStart", this), eventName));
            }
        }
        [HookMethod("EMEventEnded")]
        public void EMEventEnded(string eventName) {
            if (!Events.TryGetValue(eventName, out var ei)) return;
            ei.manually_started = false;
        }
        [HookMethod("EMRemoveEvent")]
        public void EMRemoveEvent(string eventName) {
            Interface.CallHook("EMEndGame", eventName);
            EventInfo ei;
            if (Events.TryGetValue(eventName, out ei)) {
                if (ei.participants.Count > 0) {
                    foreach (var player in ei.participants.ToList()) {
                        EMPlayerLeaveEvent(player, eventName);
                    }
                }
                if (ei.automatic_start) automatic_Events.Remove(eventName);
            }
            Events.Remove(eventName);
            Puts(string.Format(lang.GetMessage("RemovedEvent", this), eventName));
        }
        [HookMethod("EMCreateEvent")]
        private void EMCreateEvent(string eventName, bool automatic_start, bool stripItems, bool leaves_event_on_death, bool full_health_on_join, bool give_items_back_on_respawn, bool full_metabolism_on_join, Vector3 teleport_destination, bool restricted_metabolism = true, bool allow_teams = true) {
            if (Events.ContainsKey(eventName)) EMRemoveEvent(eventName);
            EventInfo ei;
            Events.Add(eventName, ei = new EventInfo(automatic_start, stripItems, leaves_event_on_death, full_health_on_join, give_items_back_on_respawn, full_metabolism_on_join, teleport_destination, restricted_metabolism, allow_teams));
            Puts(lang.GetMessage("SetupEvent", this), eventName);
            if (automatic_start && !automatic_Events.Contains(eventName)) {
                automatic_Events.Add(eventName);
            }
        }
        [HookMethod("EMUpdateLobby")]
        private void EMUpdateLobby(string eventName, Vector3 pos) {
            EventInfo ei;
            if (!Events.TryGetValue(eventName, out ei)) return;
            ei.teleport_destination = pos;
        }
        [HookMethod("EMStartEvent")]
        private void EMStartEvent(string eventName) {
            EventInfo ei;
            if (!Events.TryGetValue(eventName, out ei)) return;
            if (!EventRunning.ContainsKey(eventName)) EventRunning.Add(eventName, true);
            else EventRunning[eventName] = true;
            SendDiscordMsg(string.Format(lang.GetMessage("DiscordMessageEventStarted", this), eventName.TitleCase()));
        }
        [HookMethod("EMEndEvent")]
        private void EMEndEvent(string eventName) {
            if (EventRunning.ContainsKey(eventName)) {
                EventInfo ei;
                if (eventName == null || !Events.TryGetValue(eventName, out ei)) return;
                if (ei.participants.Count > 0) {
                    foreach (var player in ei.participants.ToList()) {
                        EMPlayerLeaveEvent(player, eventName);
                    }
                }
                ei.participants.Clear();
                ei.manually_started = false;
                if (!ei.allow_Teams) {
                    HandleEndGameRestoration();
                    SetLeaders();
                    ClearTeamCache();
                }
                EventRunning.Remove(eventName);
                //Interface.CallHook("EMEndGame", eventName);
                Puts(lang.GetMessage("EndedEvent", this));
            }
        }
        [HookMethod("EMEnrollPlayer")]
        private bool EMEnrollPlayer(BasePlayer player, string eventName) {
            EventInfo ei;
            if (!Events.TryGetValue(eventName, out ei)) {
                Puts(string.Format(lang.GetMessage("EventNotRegistered", this), eventName));
                return false;
            }
            if (ei.participants.Contains(player)) {
                PrintToChat(player, lang.GetMessage("AlreadyEnrolled", this, player.UserIDString));
                return false;
            }
            var playerData = GetPlayer(player.userID);
            if (!CanJoinEvent(player, eventName, playerData)) return false;
            if (ei.strip_items && !StorePlayerItems(player, playerData)) {
                ulong userID = player.userID;
                ServerMgr.Instance.Invoke(() => {
                    if (RestoreItems(player, playerData)) {
                        Interface.Oxide.CallHook("OnPlayerItemsRestored", player);
                        pcdData.pEntity.Remove(player.userID);
                    }
                }
                , 1);
                PrintToChat(player, lang.GetMessage("FailedToStrip", this, player.UserIDString));
                return false;
            }
            StorePlayerInfo(player, ei.full_health_on_join, ei.full_metabolism_on_join, ei.restricted_temp);
            if (!ei.allow_Teams) HandleTeam(player, true);
            ei.participants.Add(player);
            TeleportToEvent(player, ei.teleport_destination, true);
            playerData.AtEvent = true;
            playerData.Event = eventName;
            Interface.CallHook("EMOnEventJoined", player, eventName);
            if (config.announce_player_join) AnnouncePlayerJoin(player, eventName);
            return true;
        }
        void AnnouncePlayerJoin(BasePlayer player, string eventName) {
            string prefix = Convert.ToString(Interface.CallHook("EMGetAnnounceJoinPrefix", player, eventName));
            string message = ValidJoinMessages.Count > 0 ? ValidJoinMessages.GetRandom() : "JointAnnounceMsg_1";
            var eventTitle = eventName.TitleCase();
            foreach (var p in BasePlayer.activePlayerList) PrintToChat(p, (!string.IsNullOrEmpty(prefix) ? prefix + " " : null) + string.Format(lang.GetMessage(message, this, p.UserIDString), player.displayName, eventTitle));
        }
        List<string> ValidJoinMessages = new List<string>();
        [HookMethod("EMPlayerLeaveEvent")]
        private void EMPlayerLeaveEvent(BasePlayer player, string eventName = null, bool manually_left = false) {
            if (!IsPlayerSetup(player.userID)) {
                if (manually_left) PrintToChat(player, lang.GetMessage("NoEventData", this, player.UserIDString));
                return;
            }
            var playerData = GetPlayer(player.userID);
            EventInfo ei;
            if (eventName != null) Events.TryGetValue(eventName, out ei);
            else ei = null;
            WasAtEvent[player.userID] = playerData.Event;
            RemoveFromEvent(player, playerData.Event);
            timer.Once(1f, () => WasAtEvent.Remove(player.userID));
            RestoreStats(player, playerData);
            playerData.StripOnItemRestore = true;
            if (ei == null || ei.give_items_back_automatically) playerData.RestoreOnWake = true;
            playerData.AtEvent = false;
            if (!ei.give_items_back_automatically && playerData.Items.Count > 0) PrintToChat(player, string.Format(lang.GetMessage("ManualItemRecovery", this, player.UserIDString), config.redeem_items_command));
            if (!ei.allow_Teams) HandleTeam(player, false);
            Interface.CallHook("EMOnEventLeft", player, eventName);
        }
        //Related to chat commandf
        void RestoreItemsCMD(BasePlayer player) {
            HandleFromCMD(player);
        }
        void HandleFromCMD(BasePlayer player) {
            var playerData = GetPlayer(player.userID, false);
            if (playerData == null) {
                PrintToChat(player, "No data.");
                return;
            }
            bool needsTP = playerData.Location != Vector3.zero;
            RestoreStats(player, playerData);
            playerData.StripOnItemRestore = false;
            PrintToChat(player, "Restoring items.");
            if (!needsTP) player.Invoke(() => HandleItemRestore(player, playerData), 1);
            else playerData.RestoreOnWake = true;
        }
#endregion
#region API Stuff
        List<Item> AllItems(BasePlayer player) {
            List<Item> result = Pool.Get<List<Item>>();
            if (player.inventory.containerMain?.itemList != null) result.AddRange(player.inventory.containerMain.itemList);
            if (player.inventory.containerBelt?.itemList != null) result.AddRange(player.inventory.containerBelt.itemList);
            if (player.inventory.containerWear?.itemList != null) result.AddRange(player.inventory.containerWear.itemList);
            return result;
        }
        [HookMethod("EMPlayerDiedAtEvent")]
        public bool EMPlayerDiedAtEvent(BasePlayer player) {
            if (EMAtEvent(player.userID)) return true;
            return WasAtEvent.ContainsKey(player.userID);
        }
        [HookMethod("EMPlayerDiedAtSpecificEvent")]
        public bool EMPlayerDiedAtSpecificEvent(BasePlayer player, string eventName) {
            if (EMIsParticipating(player, eventName)) return true;
            string wasEvent;
            if (WasAtEvent.TryGetValue(player.userID, out wasEvent) && wasEvent.Equals(eventName, StringComparison.OrdinalIgnoreCase)) return true;
            return false;
        }
        object STOnPouchOpen(BasePlayer player) {
            if (EMAtEvent(player.userID)) return true;
            return null;
        }
        [HookMethod("EMExternalPluginSettings")]
        void EMExternalPluginSettings(string eventName, bool canDropBackpack = false, bool canEraseBackpack = false, bool canOpenBackpack = false, bool canBackpackAcceptItem = false, bool canRedeemKit = false, bool CanLoseXP = false) {
            EventInfo ei;
            if (!Events.TryGetValue(eventName, out ei)) {
                Puts(string.Format(lang.GetMessage("EventNotSetupExternalPluginSettings", this), eventName));
                return;
            }
            Puts($"Setting up external plugin settings: eventName: {eventName}. canDropBackpack: {canDropBackpack}. canEraseBackpack: {canEraseBackpack}. canOpenBackpack: {canOpenBackpack}. canBackpackAcceptItem: {canBackpackAcceptItem}. canRedeemKit: {canRedeemKit}. CanLoseXP: {CanLoseXP}.");
            ei.external_plugin_settings = new EventInfo.ExternalPluginSettings(canDropBackpack, canEraseBackpack, canOpenBackpack, canBackpackAcceptItem, canRedeemKit, CanLoseXP);
        }
        [HookMethod("EMBlackListCommands")]
        void EMBlackListCommands(string eventName, string[] commands) {
// ... [Code preview truncated due to length. Full source in attached file] ...

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