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

FREE ZoneManager : 2.4.11 2.4.11

Нет прав для скачивания
C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
// Reference: RustBuild

using System.Collections.Generic;
using System;
using System.Globalization;
using System.Linq;
using System.Reflection;

using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;

using UnityEngine;

using Oxide.Core;
using Oxide.Core.Configuration;
using Oxide.Core.Plugins;

using Rust;

namespace Oxide.Plugins
{
    [Info("ZoneManager", "Reneb / Nogrod", "2.4.11", ResourceId = 739)]
    public class ZoneManager : RustPlugin
    {
        private const string PermZone = "zonemanager.zone";
        private const string PermCanDeploy = "zonemanager.candeploy";
        private const string PermCanBuild = "zonemanager.canbuild";

        [PluginReference]
        Plugin PopupNotifications;

        ////////////////////////////////////////////
        /// Configs
        ////////////////////////////////////////////
        private bool usePopups = false;
        private bool Changed;
        private bool Initialized;
        private float AutolightOnTime;
        private float AutolightOffTime;
        private string prefix;

        private object GetConfig(string menu, string datavalue, object defaultValue)
        {
            var data = Config[menu] as Dictionary<string, object>;
            if (data == null)
            {
                data = new Dictionary<string, object>();
                Config[menu] = data;
                Changed = true;
            }
            object value;
            if (!data.TryGetValue(datavalue, out value))
            {
                value = defaultValue;
                data[datavalue] = value;
                Changed = true;
            }
            return value;
        }

        private static bool GetBoolValue(string value)
        {
            if (string.IsNullOrEmpty(value)) return false;
            value = value.Trim().ToLower();
            switch (value)
            {
                case "t":
                case "true":
                case "1":
                case "yes":
                case "y":
                case "on":
                    return true;
                default:
                    return false;
            }
        }
        private static BasePlayer FindPlayer(string nameOrIdOrIp)
        {
            foreach (var activePlayer in BasePlayer.activePlayerList)
            {
                if (activePlayer.UserIDString == nameOrIdOrIp)
                    return activePlayer;
                if (activePlayer.displayName.Contains(nameOrIdOrIp, CompareOptions.OrdinalIgnoreCase))
                    return activePlayer;
                if (activePlayer.net?.connection != null && activePlayer.net.connection.ipaddress == nameOrIdOrIp)
                    return activePlayer;
            }
            foreach (var sleepingPlayer in BasePlayer.sleepingPlayerList)
            {
                if (sleepingPlayer.UserIDString == nameOrIdOrIp)
                    return sleepingPlayer;
                if (sleepingPlayer.displayName.Contains(nameOrIdOrIp, CompareOptions.OrdinalIgnoreCase))
                    return sleepingPlayer;
            }
            return null;
        }
        private void LoadVariables()
        {
            AutolightOnTime = Convert.ToSingle(GetConfig("AutoLights", "Lights On Time", "18.0"));
            AutolightOffTime = Convert.ToSingle(GetConfig("AutoLights", "Lights Off Time", "8.0"));
            prefix = Convert.ToString(GetConfig("Chat", "Prefix", "<color=#FA58AC>ZoneManager:</color> "));

            if (!Changed) return;
            SaveConfig();
            Changed = false;
        }

        protected override void LoadDefaultConfig()
        {
            Config.Clear();
            LoadVariables();
        }


        ////////////////////////////////////////////
        /// FIELDS
        ////////////////////////////////////////////

        private readonly Dictionary<string, ZoneDefinition> ZoneDefinitions = new Dictionary<string, ZoneDefinition>();
        private readonly Dictionary<ulong, string> LastZone = new Dictionary<ulong, string>();
        private readonly Dictionary<BasePlayer, HashSet<Zone>> playerZones = new Dictionary<BasePlayer, HashSet<Zone>>();
        private readonly Dictionary<BaseCombatEntity, HashSet<Zone>> buildingZones = new Dictionary<BaseCombatEntity, HashSet<Zone>>();
        private readonly Dictionary<BaseNPC, HashSet<Zone>> npcZones = new Dictionary<BaseNPC, HashSet<Zone>>();
        private readonly Dictionary<ResourceDispenser, HashSet<Zone>> resourceZones = new Dictionary<ResourceDispenser, HashSet<Zone>>();
        private readonly Dictionary<BaseEntity, HashSet<Zone>> otherZones = new Dictionary<BaseEntity, HashSet<Zone>>();
        private readonly Dictionary<BasePlayer, ZoneFlags> playerTags = new Dictionary<BasePlayer, ZoneFlags>();

        private ZoneFlags disabledFlags = ZoneFlags.None;
        private DynamicConfigFile ZoneManagerData;
        private StoredData storedData;
        private Zone[] zoneObjects = new Zone[0];

        private static readonly FieldInfo decay = typeof(DecayEntity).GetField("decay", BindingFlags.Instance | BindingFlags.NonPublic);
        private static readonly FieldInfo decayTimer = typeof(DecayEntity).GetField("decayTimer", BindingFlags.Instance | BindingFlags.NonPublic);
        private static readonly FieldInfo decayDelayTime = typeof(DecayEntity).GetField("decayDelayTime", BindingFlags.Instance | BindingFlags.NonPublic);
        private static readonly FieldInfo decayDeltaTime = typeof(DecayEntity).GetField("decayDeltaTime", BindingFlags.Instance | BindingFlags.NonPublic);

        private readonly FieldInfo npcNextTick = typeof(NPCAI).GetField("nextTick", (BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance | BindingFlags.NonPublic));
        //private static readonly int triggerLayer = LayerMask.NameToLayer("Trigger");
        private static readonly int playersMask = LayerMask.GetMask("Player (Server)");
        //private static readonly int buildingMask = LayerMask.GetMask("Deployed", "Player (Server)", "Default", "Prevent Building");

        private static readonly Collider[] colBuffer = (Collider[])typeof(Vis).GetField("colBuffer", (BindingFlags.Static | BindingFlags.NonPublic))?.GetValue(null);

        /////////////////////////////////////////
        // Zone
        // is a Monobehavior
        // used to detect the colliders with players
        // and created everything on it's own (radiations, locations, etc)
        /////////////////////////////////////////

        private static float GetSkyHour()
        {
            return TOD_Sky.Instance.Cycle.Hour;
        }

        public class Zone : MonoBehaviour
        {
            public ZoneDefinition Info;
            public ZoneManager ZoneManagerPlugin;
            public ZoneFlags disabledFlags = ZoneFlags.None;

            public readonly HashSet<ulong> WhiteList = new HashSet<ulong>();
            public readonly HashSet<ulong> KeepInList = new HashSet<ulong>();

            private HashSet<BasePlayer> players = new HashSet<BasePlayer>();
            private HashSet<BaseCombatEntity> buildings = new HashSet<BaseCombatEntity>();

            private bool lightsOn;

            private readonly FieldInfo meshLookupField = typeof(MeshColliderBatch).GetField("meshLookup", BindingFlags.Instance | BindingFlags.NonPublic);
			private static FieldInfo secondsRemaining = typeof(SearchLight).GetField("secondsRemaining", (BindingFlags.Instance | BindingFlags.NonPublic));

            private void Awake()
            {
                gameObject.layer = (int)Layer.Reserved1; //hack to get all trigger layers...otherwise child zones
                gameObject.name = "Zone Manager";

                var rigidbody = gameObject.AddComponent<Rigidbody>();
                rigidbody.useGravity = false;
                rigidbody.isKinematic = true;
                rigidbody.detectCollisions = true;
                rigidbody.collisionDetectionMode = CollisionDetectionMode.Discrete;
            }

            private void UpdateCollider()
            {
                var sphereCollider = gameObject.GetComponent<SphereCollider>();
                var boxCollider = gameObject.GetComponent<BoxCollider>();
                if (Info.Size != Vector3.zero)
                {
                    if (sphereCollider != null) Destroy(sphereCollider);
                    if (boxCollider == null)
                    {
                        boxCollider = gameObject.AddComponent<BoxCollider>();
                        boxCollider.isTrigger = true;
                    }
                    boxCollider.size = Info.Size;
                }
                else
                {
                    if (boxCollider != null) Destroy(boxCollider);
                    if (sphereCollider == null)
                    {
                        sphereCollider = gameObject.AddComponent<SphereCollider>();
                        sphereCollider.isTrigger = true;
                    }
                    sphereCollider.radius = Info.Radius;
                }
            }

            public void SetInfo(ZoneDefinition info)
            {
                Info = info;
                if (Info == null) return;
                gameObject.name = $"Zone Manager({Info.Id})";
                transform.position = Info.Location;
                transform.rotation = Quaternion.Euler(Info.Rotation);
                UpdateCollider();
                gameObject.SetActive(Info.Enabled);
                enabled = Info.Enabled;

                if (ZoneManagerPlugin.HasZoneFlag(this, ZoneFlags.AlwaysLights))
                {
                    if (IsInvoking("CheckAlwaysLights")) CancelInvoke("CheckAlwaysLights");
                    InvokeRepeating("CheckAlwaysLights", 5f, 60f);
                }
                else if (ZoneManagerPlugin.HasZoneFlag(this, ZoneFlags.AutoLights))
                {
                    var currentTime = GetSkyHour();

                    if (currentTime > ZoneManagerPlugin.AutolightOffTime && currentTime < ZoneManagerPlugin.AutolightOnTime)
                        lightsOn = true;
                    else
                        lightsOn = false;
                    if (IsInvoking("CheckLights")) CancelInvoke("CheckLights");
                    InvokeRepeating("CheckLights", 5f, 30f);
                }

                var radiation = gameObject.GetComponent<TriggerRadiation>();
                if (Info.Radiation > 0)
                {
                    radiation = radiation ?? gameObject.AddComponent<TriggerRadiation>();
                    radiation.RadiationAmountOverride = Info.Radiation;
                    radiation.radiationSize = Info.Radius;
                    radiation.interestLayers = playersMask;
                    radiation.enabled = Info.Enabled;
                }
                else if (radiation != null)
                {
                    radiation.RadiationAmountOverride = 0;
                    radiation.radiationSize = 0;
                    radiation.interestLayers = playersMask;
                    radiation.enabled = false;
                    //Destroy(radiation);
                }

                var comfort = gameObject.GetComponent<TriggerComfort>();
                if (Info.Comfort > 0)
                {
                    comfort = comfort ?? gameObject.AddComponent<TriggerComfort>();
                    comfort.baseComfort = Info.Comfort;
                    comfort.triggerSize = Info.Radius;
                    comfort.interestLayers = playersMask;
                    comfort.enabled = Info.Enabled;
                }
                else if (comfort != null)
                {
                    comfort.baseComfort = 0;
                    comfort.triggerSize = 0;
                    comfort.interestLayers = playersMask;
                    comfort.enabled = false;
                    //Destroy(comfort);
                }

                if (IsInvoking("CheckEntites")) CancelInvoke("CheckEntites");
                InvokeRepeating("CheckEntites", 10f, 10f);
                /*if (HasAnyFlag(info.flags, ZoneFlags.Eject | ZoneFlags.EjectSleepers
                    | ZoneFlags.KillSleepers | ZoneFlags.NoBleed | ZoneFlags.NoBoxLoot | ZoneFlags.NoBuild
                    | ZoneFlags.NoChat | ZoneFlags.NoDeploy | ZoneFlags.NoDrown | ZoneFlags.NoKits
                    | ZoneFlags.NoPlayerLoot | ZoneFlags.NoRemove | ZoneFlags.NoSuicide | ZoneFlags.NoTp
                    | ZoneFlags.NoUpgrade | ZoneFlags.NoWounded | ZoneFlags.PveGod | ZoneFlags.PvpGod
                    | ZoneFlags.SleepGod | ZoneFlags.AutoLights))
                {
                    Interface.Oxide.LogInfo("Mask: Player (Server)");
                }*/
            }

            private void CheckEntites()
            {
                if (ZoneManagerPlugin == null) return;
                var oldPlayers = players;
                players = new HashSet<BasePlayer>();
                int entities;
                if (Info.Size != Vector3.zero)
                    entities = Physics.OverlapBoxNonAlloc(Info.Location, Info.Size/2, colBuffer, Quaternion.Euler(Info.Rotation), playersMask);
                else
                    entities = Physics.OverlapSphereNonAlloc(Info.Location, Info.Radius, colBuffer, playersMask);
                for (var i = 0; i < entities; i++)
                {
                    var player = colBuffer[i].GetComponentInParent<BasePlayer>();
                    colBuffer[i] = null;
                    if (player != null)
                    {
                        if (players.Add(player) && !oldPlayers.Contains(player))
                            ZoneManagerPlugin.OnPlayerEnterZone(this, player);
                    }
                }
                foreach (var player in oldPlayers)
                {
                    if (!players.Contains(player))
                        ZoneManagerPlugin.OnPlayerExitZone(this, player);
                }
            }

            private void OnDestroy()
            {
                CancelInvoke("CheckLights");
                CancelInvoke("CheckAlwaysLights");
                ZoneManagerPlugin.OnZoneDestroy(this);
                ZoneManagerPlugin = null;
                Destroy(gameObject);
            }

            private void CheckLights()
            {
                if (ZoneManagerPlugin == null) return;
                var currentTime = GetSkyHour();
                if (currentTime > ZoneManagerPlugin.AutolightOffTime && currentTime < ZoneManagerPlugin.AutolightOnTime)
                {
                    if (!lightsOn) return;
                    foreach (var building in buildings)
                    {
                        var oven = building as BaseOven;
                        if (oven != null && !oven.IsInvoking("Cook"))
                        {
                            oven.SetFlag(BaseEntity.Flags.On, false);
                            continue;
                        }
                        var door = building as Door;
                        if (door != null && door.PrefabName.Contains("shutter"))
                            door.SetFlag(BaseEntity.Flags.Open, true);

						var light = building as SearchLight;
						if (light != null)
                        {
                            light.SetFlag(BaseEntity.Flags.On, false);
                            secondsRemaining.SetValue(light, 0);
                        }
                    }
                    foreach (var player in players)
                    {
                        if (player.userID >= 76560000000000000L || player.inventory?.containerWear?.itemList == null) continue; //only npc
                        var items = player.inventory.containerWear.itemList;
                        foreach (var item in items)
                        {
                            if (!item.info.shortname.Equals("hat.miner") && !item.info.shortname.Equals("hat.candle")) continue;
                            item.SwitchOnOff(false, player);
                            player.inventory.ServerUpdate(0f);
                            break;
                        }
                    }
                    lightsOn = false;
                }
                else
                {
                    if (lightsOn) return;
                    foreach (var building in buildings)
                    {
                        var oven = building as BaseOven;
                        if (oven != null && !oven.IsInvoking("Cook"))
                        {
                            oven.SetFlag(BaseEntity.Flags.On, true);
                            continue;
                        }
                        var door = building as Door;
                        if (door != null && door.PrefabName.Contains("shutter"))
                            door.SetFlag(BaseEntity.Flags.Open, false);

						var light = building as SearchLight;
						if (light != null)
                        {
                            light.SetFlag(BaseEntity.Flags.On, true);
                            secondsRemaining.SetValue(light, 900);
                        }
                    }
                    var fuel = ItemManager.FindItemDefinition("lowgradefuel");
                    foreach (var player in players)
                    {
                        if (player.userID >= 76560000000000000L || player.inventory?.containerWear?.itemList == null) continue; // only npc
                        var items = player.inventory.containerWear.itemList;
                        foreach (var item in items)
                        {
                            if (!item.info.shortname.Equals("hat.miner") && !item.info.shortname.Equals("hat.candle")) continue;
                            if (item.contents == null) item.contents = new ItemContainer();
                            var array = item.contents.itemList.ToArray();
                            for (var i = 0; i < array.Length; i++)
                                array[i].Remove(0f);
                            var newItem = ItemManager.Create(fuel, 100);
                            newItem.MoveToContainer(item.contents);
                            item.SwitchOnOff(true, player);
                            player.inventory.ServerUpdate(0f);
                            break;
                        }
                    }
                    lightsOn = true;
                }
            }
            private void CheckAlwaysLights()
            {
                if (ZoneManagerPlugin == null) return;
                foreach (var building in buildings)
                {
                    var oven = building as BaseOven;
                    if (oven == null || oven.IsInvoking("Cook")) continue;
                    oven.SetFlag(BaseEntity.Flags.On, true);
                }
            }

            public void OnEntityKill(BaseCombatEntity entity)
            {
                var player = entity as BasePlayer;
                if (player != null)
                    players.Remove(player);
                else if (entity != null && !(entity is LootContainer) && !(entity is BaseHelicopter) && !(entity is BaseNPC))
                    buildings.Remove(entity);
            }

            private void CheckCollisionEnter(Collider col)
            {
                if (ZoneManagerPlugin.HasZoneFlag(this, ZoneFlags.NoDecay))
                {
                    var decayEntity = col.GetComponentInParent<DecayEntity>();
                    if (decayEntity != null && decay.GetValue(decayEntity) != null)
                    {
                        decayEntity.CancelInvoke("RunDecay");
                        decayTimer.SetValue(decayEntity, 0f);
                    }
                }
                var resourceDispenser = col.GetComponentInParent<ResourceDispenser>();
                if (resourceDispenser != null) //also BaseCorpse
                {
                    ZoneManagerPlugin.OnResourceEnterZone(this, resourceDispenser);
                    return;
                }
                var entity = col.GetComponentInParent<BaseEntity>();
                if (entity == null) return;
                var npc = entity as BaseNPC;
                if (npc != null)
                {
                    ZoneManagerPlugin.OnNpcEnterZone(this, npc);
                    return;
                }
                var combatEntity = entity as BaseCombatEntity;
                if (combatEntity != null && !(entity is LootContainer) && !(entity is BaseHelicopter))
                {
                    buildings.Add(combatEntity);
                    ZoneManagerPlugin.OnBuildingEnterZone(this, combatEntity);
                }
                else
                {
                    ZoneManagerPlugin.OnOtherEnterZone(this, entity);
                }
            }

            private void CheckCollisionLeave(Collider col)
            {
                if (ZoneManagerPlugin.HasZoneFlag(this, ZoneFlags.NoDecay))
                {
                    var decayEntity = col.GetComponentInParent<DecayEntity>();
                    if (decayEntity != null && decay.GetValue(decayEntity) != null && !decayEntity.IsInvoking("RunDecay"))
                        decayEntity.InvokeRepeating("RunDecay", (float) decayDelayTime.GetValue(decayEntity), (float) decayDeltaTime.GetValue(decayEntity));
                }
                var resourceDispenser = col.GetComponentInParent<ResourceDispenser>();
                if (resourceDispenser != null)
                {
                    ZoneManagerPlugin.OnResourceExitZone(this, resourceDispenser);
                    return;
                }
                var entity = col.GetComponentInParent<BaseEntity>();
                if (entity == null) return;
                var npc = entity as BaseNPC;
                if (npc != null)
                {
                    ZoneManagerPlugin.OnNpcExitZone(this, npc);
                    return;
                }
                var combatEntity = entity as BaseCombatEntity;
                if (combatEntity != null && !(entity is LootContainer) && !(entity is BaseHelicopter))
                {
                    buildings.Remove(combatEntity);
                    ZoneManagerPlugin.OnBuildingExitZone(this, combatEntity);
                }
                else
                {
                    ZoneManagerPlugin.OnOtherExitZone(this, entity);
                }
            }

            private void OnTriggerEnter(Collider col)
            {
                //Interface.Oxide.LogInfo("Enter {0}: {1}", Info.ID, col.name);
                var player = col.GetComponentInParent<BasePlayer>();
                if (player != null)
                {
                    if (!players.Add(player)) return;
                    ZoneManagerPlugin.OnPlayerEnterZone(this, player);
                }
                else if (!col.transform.CompareTag("MeshColliderBatch"))
                    CheckCollisionEnter(col);
                else
                {
                    var colliderBatch = col.GetComponent<MeshColliderBatch>();
                    if (colliderBatch == null) return;
                    var colliders = ((MeshColliderLookup) meshLookupField.GetValue(colliderBatch)).src.data;
                    var bounds = gameObject.GetComponent<Collider>().bounds;
                    foreach (var instance in colliders)
                        if (instance.collider && instance.collider.bounds.Intersects(bounds))
                            CheckCollisionEnter(instance.collider);
                }
            }

            private void OnTriggerExit(Collider col)
            {
                //Interface.Oxide.LogInfo("Exit {0}: {1}", Info.ID, col.name);
                var player = col.GetComponentInParent<BasePlayer>();
                if (player != null)
                {
                    if (!players.Remove(player)) return;
                    ZoneManagerPlugin.OnPlayerExitZone(this, player);
                }
                else if(!col.transform.CompareTag("MeshColliderBatch"))
                    CheckCollisionLeave(col);
                else
                {
                    var colliderBatch = col.GetComponent<MeshColliderBatch>();
                    if (colliderBatch == null) return;
                    var colliders = ((MeshColliderLookup)meshLookupField.GetValue(colliderBatch)).src.data;
                    var bounds = gameObject.GetComponent<Collider>().bounds;
                    foreach (var instance in colliders)
                        if (instance.collider && instance.collider.bounds.Intersects(bounds))
                            CheckCollisionLeave(instance.collider);
                }
            }
        }

        /////////////////////////////////////////
        // ZoneDefinition
        // Stored informations on the zones
        /////////////////////////////////////////
        public class ZoneDefinition
        {

            public string Name;
            public float Radius;
            public float Radiation;
            public float Comfort;
            public Vector3 Location;
            public Vector3 Size;
            public Vector3 Rotation;
            public string Id;
            public string EnterMessage;
            public string LeaveMessage;
            public bool Enabled = true;
            public ZoneFlags Flags;

            public ZoneDefinition()
            {

            }

            public ZoneDefinition(Vector3 position)
            {
                Radius = 20f;
                Location = position;
            }

        }
        [Flags]
        public enum ZoneFlags : ulong
        {
            None = 0L,
            AutoLights = 1UL,
            Eject = 1UL << 1,
            PvpGod = 1UL << 2,
            PveGod = 1UL << 3,
            SleepGod = 1UL << 4,
            UnDestr = 1UL << 5,
            NoBuild = 1UL << 6,
            NoTp = 1UL << 7,
            NoChat = 1UL << 8,
            NoGather = 1UL << 9,
            NoPve = 1UL << 10,
            NoWounded = 1UL << 11,
            NoDecay = 1UL << 12,
            NoDeploy = 1UL << 13,
            NoKits = 1UL << 14,
            NoBoxLoot = 1UL << 15,
            NoPlayerLoot = 1UL << 16,
            NoCorpse = 1UL << 17,
            NoSuicide = 1UL << 18,
            NoRemove = 1UL << 19,
            NoBleed = 1UL << 20,
            KillSleepers = 1UL << 21,
            NpcFreeze = 1UL << 22,
            NoDrown = 1UL << 23,
            NoStability = 1UL << 24,
            NoUpgrade = 1UL << 25,
            EjectSleepers = 1UL << 26,
            NoPickup = 1UL << 27,
            NoCollect = 1UL << 28,
            NoDrop = 1UL << 29,
			Kill = 1UL << 30,
            NoCup = 1UL << 31,
            AlwaysLights = 1UL << 32,
            NoTrade = 1UL << 33
        }

        private bool HasZoneFlag(Zone zone, ZoneFlags flag)
        {
            if ((disabledFlags & flag) == flag) return false;
            return (zone.Info.Flags & ~zone.disabledFlags & flag) == flag;
        }
        private static bool HasAnyFlag(ZoneFlags flags, ZoneFlags flag)
        {
            return (flags & flag) != ZoneFlags.None;
        }
        private static bool HasAnyZoneFlag(Zone zone)
        {
            return (zone.Info.Flags & ~zone.disabledFlags) != ZoneFlags.None;
        }
        private static void AddZoneFlag(ZoneDefinition zone, ZoneFlags flag)
        {
            zone.Flags |= flag;
        }
        private static void RemoveZoneFlag(ZoneDefinition zone, ZoneFlags flag)
        {
            zone.Flags &= ~flag;
        }
        /////////////////////////////////////////
        // Data Management
        /////////////////////////////////////////
        private class StoredData
        {
            public readonly HashSet<ZoneDefinition> ZoneDefinitions = new HashSet<ZoneDefinition>();
        }

        private void SaveData()
        {
            ZoneManagerData.WriteObject(storedData);
        }

        private void LoadData()
        {
            ZoneDefinitions.Clear();
            try
            {
                ZoneManagerData.Settings.NullValueHandling = NullValueHandling.Ignore;
                storedData = ZoneManagerData.ReadObject<StoredData>();
                Puts("Loaded {0} Zone definitions", storedData.ZoneDefinitions.Count);
            }
            catch
            {
                Puts("Failed to load StoredData");
                storedData = new StoredData();
            }
            ZoneManagerData.Settings.NullValueHandling = NullValueHandling.Include;
            foreach (var zonedef in storedData.ZoneDefinitions)
                ZoneDefinitions[zonedef.Id] = zonedef;
        }

        private void SetupCollectibleEntity()
        {
            var collectibleEntities = Resources.FindObjectsOfTypeAll<CollectibleEntity>();
            //Puts("Found {0} CollectibleEntities.", collectibleEntities.Length);
            for (var i = 0; i < collectibleEntities.Length; i++)
            {
                var collectibleEntity = collectibleEntities[i];
                var collider = collectibleEntity.GetComponent<Collider>() ?? collectibleEntity.gameObject.AddComponent<BoxCollider>();
                collider.isTrigger = true;
            }
        }

        /////////////////////////////////////////
        // OXIDE HOOKS
        /////////////////////////////////////////

        /////////////////////////////////////////
        // Loaded()
        // Called when the plugin is loaded
        /////////////////////////////////////////
        private void Loaded()
        {
            //Puts("ZoneManager loaded: {0}", GetHashCode());
            ZoneManagerData = Interface.Oxide.DataFileSystem.GetFile("ZoneManager");
            ZoneManagerData.Settings.Converters = new JsonConverter[] { new StringEnumConverter(), new UnityVector3Converter(), };
            permission.RegisterPermission(PermZone, this);
            permission.RegisterPermission(PermCanDeploy, this);
            permission.RegisterPermission(PermCanBuild, this);
            /* for(int i = 0; i < 25; i ++)
             {
                 Debug.Log(UnityEngine.LayerMask.LayerToName(i));
             }*/
            LoadData();
            LoadVariables();
            /*string[] options = new string[32];
            for (int i = 0; i < 32; i++)
            { // get layer names
                options[i] = i + " : " + LayerMask.LayerToName(i);
            }
            Puts("Layers: {0}", string.Join(", ", options));
            var sb = new StringBuilder();
            sb.AppendLine();
            for (int i = 0; i < 32; i++)
            {
                sb.Append(i + ":\t");
                for (int j = 0; j < 32; j++)
                {
                    sb.Append(Physics.GetIgnoreLayerCollision(i, j) ? "  " : "X ");
                }
                sb.AppendLine();
            }
            Puts(sb.ToString());*/
        }
        /////////////////////////////////////////
        // Unload()
        // Called when the plugin is unloaded
        /////////////////////////////////////////
        private void Unload()
        {
            foreach (var zone in zoneObjects)
                UnityEngine.Object.Destroy(zone);
            var collectibleEntities = Resources.FindObjectsOfTypeAll<CollectibleEntity>();
            for (var i = 0; i < collectibleEntities.Length; i++)
            {
                var collider = collectibleEntities[i].GetComponent<Collider>();
                if (collider != null) UnityEngine.Object.Destroy(collider);
            }
        }

        private void OnTerrainInitialized()
        {
            if (Initialized) return;
            SetupCollectibleEntity();
            foreach (var zoneDefinition in ZoneDefinitions.Values)
                NewZone(zoneDefinition);
            Initialized = true;
        }

        private void OnServerInitialized()
        {
            if (Initialized) return;
            var values = Enum.GetValues(typeof(ZoneFlags)).Cast<ZoneFlags>();
            foreach (var flagse in values)
            {
                Puts("{0} {1}", flagse, (ulong)flagse);
            }
            timer.In(1, () => {
                SetupCollectibleEntity();
                foreach (var zoneDefinition in ZoneDefinitions.Values)
                    NewZone(zoneDefinition);
            });
            Initialized = true;
        }

        /////////////////////////////////////////
        // OnEntityBuilt(Planner planner, GameObject gameobject)
        // Called when a buildingblock was created
        /////////////////////////////////////////
        private void OnEntityBuilt(Planner planner, GameObject gameobject)
        {
            var player = planner.GetOwnerPlayer();
            if (player == null) return;
            if (HasPlayerFlag(player, ZoneFlags.NoBuild) && !hasPermission(player, PermCanBuild))
            {
                gameobject.GetComponentInParent<BaseCombatEntity>().Kill(BaseNetworkable.DestroyMode.Gib);
                SendMessage(player, "You are not allowed to build here");
            }
        }

        private object OnStructureUpgrade(BuildingBlock buildingBlock, BasePlayer player, BuildingGrade.Enum grade)
        {
            if (HasPlayerFlag(player, ZoneFlags.NoUpgrade) && !isAdmin(player)) return false;
            return null;
        }

        /////////////////////////////////////////
        // OnItemDeployed(Deployer deployer, BaseEntity deployedEntity)
        // Called when an item was deployed
        /////////////////////////////////////////
        private void OnItemDeployed(Deployer deployer, BaseEntity deployedEntity)
        {
            var player = deployer.GetOwnerPlayer();
            if (player == null) return;
            if (HasPlayerFlag(player, ZoneFlags.NoDeploy) && !hasPermission(player, PermCanDeploy))
            {
                deployedEntity.Kill(BaseNetworkable.DestroyMode.Gib);
                SendMessage(player, "You are not allowed to deploy here");
            }
            else if (HasPlayerFlag(player, ZoneFlags.NoCup) && deployedEntity.PrefabName.Contains("cupboard"))
            {
                deployedEntity.Kill(BaseNetworkable.DestroyMode.Gib);
                SendMessage(player, "You are not allowed to deploy here");
            }
        }

        private void OnRunPlayerMetabolism(PlayerMetabolism metabolism, BaseCombatEntity ownerEntity, float delta)
        {
            var player = ownerEntity as BasePlayer;
            if (player == null) return;
            if (metabolism.bleeding.value > 0 && HasPlayerFlag(player, ZoneFlags.NoBleed))
                metabolism.bleeding.value = 0f;
            if (metabolism.oxygen.value < 1 && HasPlayerFlag(player, ZoneFlags.NoDrown))
                metabolism.oxygen.value = 1;
        }

        /////////////////////////////////////////
        // OnPlayerChat(ConsoleSystem.Arg arg)
        // Called when a user writes something in the chat, doesn't take in count the commands
        /////////////////////////////////////////
        private object OnPlayerChat(ConsoleSystem.Arg arg)
        {
            if (arg.Player() == null) return null;
            if (HasPlayerFlag(arg.Player(), ZoneFlags.NoChat))
            {
                SendMessage(arg.Player(), "You are not allowed to chat here");
                return false;
            }
            return null;
        }

        /////////////////////////////////////////
        // OnServerCommand(ConsoleSystem.Arg arg)
        // Called when a user executes a command
        /////////////////////////////////////////
        private object OnServerCommand(ConsoleSystem.Arg arg)
        {
            if (arg.Player() == null) return null;
            if (arg.cmd?.Name == null) return null;
            if (arg.cmd.Name == "kill" && HasPlayerFlag(arg.Player(), ZoneFlags.NoSuicide))
            {
                SendMessage(arg.Player(), "You are not allowed to suicide here");
                return false;
            }
            return null;
        }

        /////////////////////////////////////////
        // OnPlayerDisconnected(BasePlayer player)
        // Called when a user disconnects
        /////////////////////////////////////////
        private void OnPlayerDisconnected(BasePlayer player)
        {
            if (HasPlayerFlag(player, ZoneFlags.KillSleepers) && !isAdmin(player)) player.Die();
            else if (HasPlayerFlag(player, ZoneFlags.EjectSleepers))
            {
                HashSet<Zone> zones;
                if (!playerZones.TryGetValue(player, out zones) || zones.Count == 0) return;
                foreach (var zone in zones)
                {
                    if (HasZoneFlag(zone, ZoneFlags.EjectSleepers))
                    {
                        EjectPlayer(zone, player);
                        break;
                    }
                }
            }
        }

        private void OnPlayerAttack(BasePlayer attacker, HitInfo hitinfo)
        {
            var disp = hitinfo.HitEntity?.GetComponent<ResourceDispenser>();
            if (disp == null) return;
            HashSet<Zone> resourceZone;
            if (!resourceZones.TryGetValue(disp, out resourceZone)) return;
            foreach (var zone in resourceZone)
            {
                if (HasZoneFlag(zone, ZoneFlags.NoGather))
                {
                    hitinfo.HitEntity = null;
                    break;
                }
            }
        }

        /////////////////////////////////////////
        // OnEntityAttacked(BaseCombatEntity entity, HitInfo hitinfo)
        // Called when any entity is attacked
        /////////////////////////////////////////
        private void OnEntityTakeDamage(BaseCombatEntity entity, HitInfo hitinfo)
        {
            if (entity == null || entity.GetComponent<ResourceDispenser>() != null) return;
            var player = entity as BasePlayer;
            if (player != null)
            {
                var target = hitinfo.Initiator as BasePlayer;
                if (player.IsSleeping() && HasPlayerFlag(player, ZoneFlags.SleepGod))
                {
                    CancelDamage(hitinfo);
                }
                else if (target != null)
                {
                    if (target.userID < 76560000000000000L) return;
                    if (HasPlayerFlag(player, ZoneFlags.PvpGod))
                        CancelDamage(hitinfo);
                    else if (HasPlayerFlag(target, ZoneFlags.PvpGod))
                        CancelDamage(hitinfo);
                }
                else if (HasPlayerFlag(player, ZoneFlags.PveGod))
                    CancelDamage(hitinfo);
                else if (hitinfo.Initiator is FireBall && HasPlayerFlag(player, ZoneFlags.PvpGod))
                    CancelDamage(hitinfo);
                return;
            }
            var npcai = entity as BaseNPC;
            if (npcai != null)
            {
                HashSet<Zone> zones;
                if (!npcZones.TryGetValue(npcai, out zones)) return;
                foreach (var zone in zones)
                {
                    if (HasZoneFlag(zone, ZoneFlags.NoPve))
                    {
                        CancelDamage(hitinfo);
                        break;
                    }
                }
                return;
            }
            if (!(entity is LootContainer) && !(entity is BaseHelicopter))
            {
                var resource = entity.GetComponent<ResourceDispenser>();
                HashSet<Zone> zones;
                if (!buildingZones.TryGetValue(entity, out zones) && (resource == null || !resourceZones.TryGetValue(resource, out zones))) return;
                foreach (var zone in zones)
                {
                    if (HasZoneFlag(zone, ZoneFlags.UnDestr))
                    {
                        CancelDamage(hitinfo);
                        break;
                    }
                }
            }
            /*else
            {
                HashSet<Zone> zones;
                if (otherZones.TryGetValue(entity, out zones))
                {
                }
            }*/
        }

        private void OnEntityKill(BaseNetworkable networkable)
        {
            var entity = networkable as BaseEntity;
            if (entity == null) return;
            var resource = entity.GetComponent<ResourceDispenser>();
            if (resource != null)
            {
                HashSet<Zone> zones;
                if (resourceZones.TryGetValue(resource, out zones))
                    OnResourceExitZone(null, resource, true);
                return;
            }
            var player = entity as BasePlayer;
            if (player != null)
            {
                HashSet<Zone> zones;
                if (playerZones.TryGetValue(player, out zones))
                    OnPlayerExitZone(null, player, true);
                return;
            }
            var npc = entity as BaseNPC;
            if (npc != null)
            {
                HashSet<Zone> zones;
                if (npcZones.TryGetValue(npc, out zones))
                    OnNpcExitZone(null, npc, true);
                return;
            }
            var building = entity as BaseCombatEntity;
            if (building != null && !(entity is LootContainer) && !(entity is BaseHelicopter))
            {
                HashSet<Zone> zones;
                if (buildingZones.TryGetValue(building, out zones))
                    OnBuildingExitZone(null, building, true);
            }
            else
            {
                HashSet<Zone> zones;
                if (otherZones.TryGetValue(entity, out zones))
                    OnOtherExitZone(null, entity, true);
            }
        }


        /////////////////////////////////////////
        // OnEntitySpawned(BaseNetworkable entity)
        // Called when any kind of entity is spawned in the world
        /////////////////////////////////////////
        private void OnEntitySpawned(BaseNetworkable entity)
        {
            if (entity is BaseCorpse)
            {
                timer.Once(2f, () =>
                {
                    HashSet<Zone> zones;
                    if (entity.IsDestroyed || !resourceZones.TryGetValue(entity.GetComponent<ResourceDispenser>(), out zones)) return;
                    foreach (var zone in zones)
                    {
                        if (HasZoneFlag(zone, ZoneFlags.NoCorpse))
                        {
                            entity.KillMessage();
                            break;
                        }
                    }
                });
            }
            else if (entity is BuildingBlock && zoneObjects != null)
            {
                var block = (BuildingBlock)entity;
                foreach (var zone in zoneObjects)
                {
                    if (HasZoneFlag(zone, ZoneFlags.NoStability))
                    {
                        if (zone.Info.Size != Vector3.zero)
                        {
                            if (!new Bounds(zone.Info.Location, Quaternion.Euler(zone.Info.Rotation) * zone.Info.Size).Contains(block.transform.position))
                                continue;
                        }
                        else if (Vector3.Distance(block.transform.position, zone.Info.Location) > zone.Info.Radius)
                            continue;
                        block.grounded = true;
                        break;
                    }
                }
            }
            var npcai = entity.GetComponent<NPCAI>();
            if (npcai != null)
                npcNextTick.SetValue(npcai, Time.time + 10f);
        }

        /////////////////////////////////////////
        // OnPlayerLoot(PlayerLoot lootInventory,  BasePlayer targetPlayer)
        // Called when a player tries to loot another player
        /////////////////////////////////////////
        private object CanLootPlayer(BasePlayer target, BasePlayer looter)
        {
            return OnLootPlayerInternal(looter, target) ? null : (object) false;
        }

        private void OnLootPlayer(BasePlayer looter, BasePlayer target)
        {
            OnLootPlayerInternal(looter, target);
        }

        private bool OnLootPlayerInternal(BasePlayer looter, BasePlayer target)
        {
            if (HasPlayerFlag(looter, ZoneFlags.NoPlayerLoot) || target != null && HasPlayerFlag(target, ZoneFlags.NoPlayerLoot))
            {
                NextTick(looter.EndLooting);
                return false;
            }
            return true;
        }

        private void OnLootEntity(BasePlayer looter, BaseEntity target)
        {
            if (target is BaseCorpse)
                OnLootPlayerInternal(looter, null);
            else if (HasPlayerFlag(looter, ZoneFlags.NoBoxLoot))
            {
                if ((target as StorageContainer)?.transform.position == Vector3.zero) return;
                timer.Once(0.01f, looter.EndLooting);
            }
        }

        private object CanBeWounded(BasePlayer player, HitInfo hitinfo)
        {
            return HasPlayerFlag(player, ZoneFlags.NoWounded) ? (object) false : null;
        }

        /////////////////////////////////////////
        // Outside Plugin Hooks
        /////////////////////////////////////////

        private object canRedeemKit(BasePlayer player)
        {
            return HasPlayerFlag(player, ZoneFlags.NoKits) ? "You may not redeem a kit inside this area" : null;
        }

        private object CanTeleport(BasePlayer player)
        {
            return HasPlayerFlag(player, ZoneFlags.NoTp) ? "You may not teleport in this area" : null;
        }

        private object canRemove(BasePlayer player)
        {
            return HasPlayerFlag(player, ZoneFlags.NoRemove) ? "You may not use the remover tool in this area" : null;
        }

        private bool CanChat(BasePlayer player)
        {
            return !HasPlayerFlag(player, ZoneFlags.NoChat);
        }

        private object CanTrade(BasePlayer player)
        {
            return HasPlayerFlag(player, ZoneFlags.NoTrade) ? "You may not trade in this area" : null;
        }

        private void UpdateZoneDefinition(ZoneDefinition zone, string[] args, BasePlayer player = null)
        {
            for (var i = 0; i < args.Length; i = i + 2)
            {
                object editvalue;
                switch (args[i].ToLower())
                {
                    case "name":
                        editvalue = zone.Name = args[i + 1];
                        break;
                    case "id":
                        editvalue = zone.Id = args[i + 1];
                        break;
                    case "comfort":
                        editvalue = zone.Comfort = Convert.ToSingle(args[i + 1]);
                        break;
                    case "radiation":
                        editvalue = zone.Radiation = Convert.ToSingle(args[i + 1]);
                        break;
                    case "radius":
                        editvalue = zone.Radius = Convert.ToSingle(args[i + 1]);
                        break;
                    case "rotation":
                        zone.Rotation = player?.GetNetworkRotation() ?? Vector3.zero;/* + Quaternion.AngleAxis(90, Vector3.up).eulerAngles*/
                        zone.Rotation.x = 0;
                        editvalue = zone.Rotation;
                        break;
                    case "location":
                        if (player != null && args[i + 1].Equals("here", StringComparison.OrdinalIgnoreCase))
                        {
                            editvalue = zone.Location = player.tr
// ... [Code preview truncated due to length. Full source in attached file] ...

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