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

FREE SecurityCameras : 0.1.09 0.1.09

Нет прав для скачивания
C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
using Oxide.Core.Configuration;
using Oxide.Game.Rust.Cui;
using Oxide.Core.Plugins;
using UnityEngine;
using System.Linq;
using System.Collections;
using System.Globalization;
using Rust;
using Facepunch;

namespace Oxide.Plugins
{
    [Info("SecurityCameras", "k1lly0u", "0.1.09", ResourceId = 0)]
    class SecurityCameras : RustPlugin
    {
        #region Fields
        [PluginReference] Plugin Clans, Friends, ImageLibrary, LustyMap;

        private StoredData storedData;
        private RestoreData restoreData;
        private DynamicConfigFile data;

        static SecurityCameras ins;

        private List<CameraManager> cameraManagers = new List<CameraManager>();
        private List<Controller> controllers = new List<Controller>();
        private Dictionary<Colors, string> uiColors = new Dictionary<Colors, string>();

        static BuildingLinks linkManager;
        static bool isUnloading;
        static int layerPlcmnt;

        private bool wipeDetected;
        private bool isInitialized;       

        private byte[] signImage = null;

        const string permUse = "securitycameras.use";
        const string permIgnore = "securitycameras.ignorelimit";
       
        const string burlapSack = "assets/prefabs/misc/burlap sack/generic_world.prefab";
        const string chairPrefab = "assets/prefabs/deployable/chair/chair.deployed.prefab";
        const int cameraId = 1300054961;
        const int computerId = 1490499512;
        #endregion

        #region Oxide Hooks
        private void Loaded()
        {
            isUnloading = false;

            permission.RegisterPermission(permUse, this);
            permission.RegisterPermission(permIgnore, this);

            foreach (string key in configData.Camera.Max.Keys)
            {
                if (permission.PermissionExists(key, this))
                    continue;
                permission.RegisterPermission(key, this);
            }

            lang.RegisterMessages(Messages, this);
            data = Interface.Oxide.DataFileSystem.GetFile("securitycamera_data");
            restoreData = new RestoreData();

            linkManager = new BuildingLinks();
        }

        private void OnServerInitialized()
        {
            ins = this;
            LoadData();

            layerPlcmnt = LayerMask.GetMask("Construction", "Default", "Deployed", "World", "Terrain");

            LoadDefaultImages();            

            foreach (var color in configData.Control.UIColors)
                uiColors.Add(color.Key, UI.Color(color.Value.Color, color.Value.Alpha));

            if (wipeDetected)
            {
                storedData = new StoredData();
                SaveData();
            }
            else ServerMgr.Instance.StartCoroutine(InitializeAllCameras());
        }

        private void OnNewSave(string filename) => wipeDetected = true;

        private void OnServerSave() => SaveData();

        private void OnPlayerDisconnected(BasePlayer player)
        {
            BuildingLinks.Link link = linkManager.GetLinkOf(player);
            if (link != null)            
                link.CloseLink(); 
        }

        private void OnPlayerInput(BasePlayer player, InputState input)
        {
            if (player == null || input == null)
                return;

            if (player.GetComponent<Controller>())
                return;
            if (input.WasJustPressed(BUTTON.USE))
            {
                RaycastHit hit;
                if (Physics.SphereCast(player.eyes.position, 0.1f, Quaternion.Euler(player.serverInput.current.aimAngles) * Vector3.forward, out hit, 3f))
                {
                    DroppedItem droppedItem = hit.GetEntity()?.GetComponent<DroppedItem>();
                    if (droppedItem != null && droppedItem.item?.info?.itemid == computerId)
                    {
                        BuildingLinks.Link link = linkManager.GetLinkOf(droppedItem);
                        if (link != null)
                            OnComputerInteraction(player, link);
                    }
                }
            }
        }

        private void OnEntityTakeDamage(BaseCombatEntity entity, HitInfo info)
        {
            if (entity == null || info == null)
                return;
            linkManager.OnEntityTakeDamage(entity, info); 
        }

        private void OnEntityDeath(BaseCombatEntity entity, HitInfo info)
        {
            if (entity == null || info == null)
            {
                ItemPlacement placement = entity.GetComponent<ItemPlacement>();
                if (placement != null)
                    placement.OnPlayerDeath();
            }
        }

        private void OnEntityKill(BaseNetworkable networkable)
        {            
            if (networkable != null)
                linkManager.OnEntityDeath(networkable);                            
        }

        private object OnPlayerTick(BasePlayer player, PlayerTick msg, bool wasPlayerStalled)
        {
            Controller cameraController = player.GetComponent<Controller>();
            if (cameraController != null)
                return false;
            return null;
        }

        private object CanDismountEntity(BaseMountable mountable, BasePlayer player)
        {
            Controller controller = player.GetComponent<Controller>();
            if (controller != null)
                return false;
            return null;
        }

        private object OnPlayerCommand(ConsoleSystem.Arg arg)
        {
            BasePlayer player = arg.Player();

            if (player != null && player.GetComponent<Controller>())
            {
                string text = arg.GetString(0, "text").ToLower();

                if (text.Length > 0 && text[0] == '/' && arg.cmd.FullName == "chat.say")
                {
                    return false;
                }
            }
            return null;
        }

        private void Unload()
        {
            isUnloading = true;
            SaveData();

            foreach (BasePlayer player in BasePlayer.activePlayerList)
            {
                CuiHelper.DestroyUi(player, SCUI_Panel);
                CuiHelper.DestroyUi(player, SCUI_Overlay);
            }

            linkManager.DestroyAllLinks();
            
            controllers.Clear();
            ins = null;
            linkManager = null;
        }      
        #endregion

        #region Functions
        private IEnumerator InitializeAllCameras()
        {
            PrintWarning($"Initializing security camera entities");
            for (int i = 0; i < storedData.cameraData.Count(); i++)
            {
                CameraManager.CameraData cameraData = storedData.cameraData.ElementAt(i);
                
                yield return new WaitForSeconds(UnityEngine.Random.Range(0.1f, 0.2f));

                InitializeCamera(cameraData);
            }
            PrintWarning($"Initializing camera controller entities");
            ServerMgr.Instance.StartCoroutine(FindRegisteredSignage(BaseNetworkable.serverEntities.Where(x => x is Signage).Cast<Signage>()));
        }

        private IEnumerator FindRegisteredSignage(IEnumerable<Signage> signage)
        {
            for (int i = 0; i < signage.Count(); i++)
            {
                Signage sign = signage.ElementAt(i);

                if (sign == null || sign.IsDestroyed || !storedData.signIds.Contains(sign.net.ID))
                    continue;

                yield return new WaitForSeconds(UnityEngine.Random.Range(0.1f, 0.2f));

                InitializeSign(sign);
            }
            PrintWarning($"Entity initialization complete!");
        }

        private void InitializeCamera(CameraManager.CameraData cameraData)
        {
            CameraManager camera = SpawnDroppedItem(new Vector3(cameraData.position[0], cameraData.position[1], cameraData.position[2])).gameObject.AddComponent<CameraManager>();
            camera.SetRotation(new float[] { cameraData.baseRotation[0], cameraData.baseRotation[1], cameraData.baseRotation[2] });
        }

        private void InitializeSign(Signage sign)
        {
            BuildingLinks.Link link = linkManager.FindLinkedEntities(sign);

            if (!sign.HasFlag(BaseEntity.Flags.Locked))
                sign.SetFlag(BaseEntity.Flags.Locked, true);

            if (signImage != null)
                sign.textureID = FileStorage.server.Store(signImage, FileStorage.Type.png, sign.net.ID, 0);
            sign.SendNetworkUpdate(BasePlayer.NetworkQueue.Update);

            BaseEntity[] children = sign.children.Where(x => x.GetComponent<DroppedItem>())?.ToArray() ?? null;

            if (children != null)
            {
                for (int i = 0; i < children.Length; i++)
                {
                    sign.RemoveChild(children[i]);
                    children[i].Kill();
                }
            }

            Item item = ItemManager.CreateByItemID(computerId);
            BaseEntity worldEntity = item.CreateWorldObject(sign.transform.position);

            UnityEngine.Object.Destroy(worldEntity.GetComponent<Rigidbody>());
            UnityEngine.Object.Destroy(worldEntity.GetComponent<EntityCollisionMessage>());
            UnityEngine.Object.Destroy(worldEntity.GetComponent<PhysicsEffects>());

            DroppedItem droppedItem = worldEntity.GetComponent<DroppedItem>();
            droppedItem.allowPickup = false;
            droppedItem.CancelInvoke(droppedItem.IdleDestroy);
            droppedItem.SetParent(sign);
            droppedItem.transform.localPosition = new Vector3(0, 0, 0.3f);
            droppedItem.transform.rotation = Quaternion.Euler(0, sign.transform.eulerAngles.y + 180, 0);

            if (link != null)
                link.SetLinkController(sign, droppedItem);
        }

        private BaseEntity FindEntityFromRay(BasePlayer player)
        {
            Ray ray = new Ray(player.eyes.position, Quaternion.Euler(player.serverInput.current.aimAngles) * Vector3.forward);
            RaycastHit hit;
            if (!Physics.Raycast(ray, out hit, configData.Camera.Distance))
                return null;

            var hitEnt = hit.collider.GetComponentInParent<BaseEntity>();
            if (hitEnt != null)
                return hitEnt;
            return null;
        }

        private void OnComputerInteraction(BasePlayer player, BuildingLinks.Link link)
        {
            if (!permission.UserHasPermission(player.UserIDString, permUse))
            {
                SendReply(player, msg("noPerm", player.userID));
                return;
            }

            if (!player.IsBuildingAuthed())
            {
                SendReply(player, msg("notAuthed", player.userID));
                return;
            }

            if (link.IsInUse())            
            {
                SendReply(player, msg("controlInUse", player.userID));
                return;
            }

            link.OpenLink(player);
            DisplayToPlayer(player);
        }

        private BuildingManager.Building GetBuilding(BaseEntity entity)
        {
            BuildingManager.Building building = null;

            OBB obb = entity.WorldSpaceBounds();
            List<BuildingBlock> list = Pool.GetList<BuildingBlock>();
            Vis.Entities<BuildingBlock>(obb.position, 1.5f + obb.extents.magnitude, list, 2097152, QueryTriggerInteraction.Collide);

            if (list.Count > 0)            
                building = list[0].GetBuilding();            

            Pool.FreeList<BuildingBlock>(ref list);

            return building;
        }
               
        private bool IsValidSource(BasePlayer player, CameraManager camera)
        {            
            if (camera == null || camera.entity == null || camera.entity.IsDestroyed)
                return false;

            if (configData.Control.Authorized)
            {
                if (!player.IsBuildingAuthed())
                    return false;
            }
            
            return true;
        }

        private DroppedItem SpawnDroppedItem(Vector3 position)
        {
            BaseEntity worldEntity = CreateWorldObject(position);

            UnityEngine.Object.Destroy(worldEntity.GetComponent<Rigidbody>());
            UnityEngine.Object.Destroy(worldEntity.GetComponent<EntityCollisionMessage>());
            UnityEngine.Object.Destroy(worldEntity.GetComponent<PhysicsEffects>());

            DroppedItem droppedItem = worldEntity.GetComponent<DroppedItem>();
            droppedItem.allowPickup = false;
            droppedItem.CancelInvoke(droppedItem.IdleDestroy);            

            return droppedItem;
        }

        private BaseEntity CreateWorldObject(Vector3 pos)
        {
            Item item = ItemManager.CreateByItemID(cameraId);

            BaseEntity worldEntity = GameManager.server.CreateEntity(burlapSack, pos);
            WorldItem worldItem = worldEntity as WorldItem;
            if (worldItem != null)
                worldItem.InitializeItem(item);

            worldItem.enableSaving = false;
            worldEntity.Spawn();
            item.SetWorldEntity(worldEntity);
            return worldEntity;
        }

        private int GetMaxCameras(ulong playerId)
        {
            int max = 0;
            foreach(var entry in configData.Camera.Max)
            {
                if (permission.UserHasPermission(playerId.ToString(), entry.Key))
                {
                    if (max < entry.Value)
                        max = entry.Value;
                }                    
            }
            return max;
        }
        #endregion

        #region Components
        private class BuildingLinks
        {
            private List<Link> links = new List<Link>();

            public CameraManager[] GetCamerasOf(BasePlayer player) => links.Find(x => x.player == player)?.cameras.ToArray() ?? null;

            public CameraManager[] GetCamerasOf(Signage signage) => links.Find(x => x.signage == signage)?.cameras.ToArray() ?? null;

            public CameraManager[] GetCamerasOf(BuildingManager.Building building) => links.Find(x => x.building == building)?.cameras.ToArray() ?? null;

            public Link GetLinkOf(BuildingManager.Building building) => links.Find(x => x.building == building) ?? null;

            public Link GetLinkOf(Signage signage) => links.Find(x => x.signage == signage) ?? null;

            public Link GetLinkOf(CameraManager camera) => links.Find(x => x.cameras.Contains(camera)) ?? null;

            public Link GetLinkOf(DroppedItem computer) => links.Find(x => x.computer == computer) ?? null;

            public Link GetLinkOf(BasePlayer player) => links.Find(x => x.player == player) ?? null;

            public Link AddNewLink(BuildingManager.Building building, Signage sign, CameraManager[] cameras)
            {
                Link link = new Link(building, sign, cameras);
                links.Add(link);
                return link;
            }

            public void AddToLink(BuildingManager.Building building, CameraManager camera)
            {
                Link link = GetLinkOf(building);
                if (link != null)
                    link.cameras.Add(camera);
                else AddNewLink(building, null, new CameraManager[] { camera });                
            }

            public void RemoveFromLink(CameraManager camera)
            {
                Link link = GetLinkOf(camera);
                if (link != null)                
                    link.cameras.Remove(camera);
            }
            
            public Link FindLinkedEntities(Signage sign)
            {
                if (sign != null)
                {
                    BuildingManager.Building building = ins.GetBuilding(sign);
                    if (building != null)
                    {
                        Link link = GetLinkOf(building);
                        if (link == null)
                        {
                            CameraManager[] availableSources = ins.cameraManagers.Where(x => building.buildingBlocks.Contains(x.parent)).ToArray() ?? new CameraManager[0];
                            return AddNewLink(building, sign, availableSources);
                        }
                        else return link;
                    }
                }
                return null;
            }

            public void OnEntityTakeDamage(BaseCombatEntity entity, HitInfo info)
            {
                foreach (Link link in links)
                    link.OnEntityTakeDamage(entity, info);
            }

            public void OnEntityDeath(BaseNetworkable networkable)
            {
                for (int i = links.Count - 1; i >= 0; i--)                
                    links.ElementAt(i).OnEntityDeath(networkable);                
            }

            public void DestroyAllLinks()
            {
                foreach (Link link in links)
                    link.DestroyLink();
            }

            public class Link
            {
                public BasePlayer player { get; private set; }
                public Controller controller { get; private set; }

                public BuildingManager.Building building;
                public Signage signage;                
                public DroppedItem computer;
                public List<CameraManager> cameras;

                public Link() { }
                public Link(BuildingManager.Building building, Signage signage, CameraManager[] cameras)
                {
                    this.building = building;
                    this.signage = signage;
                    this.cameras = cameras.ToList();
                }

                public void OpenLink(BasePlayer player) => this.player = player;

                public void CloseLink(bool isFinishing = false)
                {
                    player = null;

                    if (controller != null)
                    {
                        if (!isUnloading)
                        {
                            if (ins.controllers.Contains(controller))
                                ins.controllers.Remove(controller);
                        }

                        if (!isFinishing)
                            controller.FinishSpectating();
                        controller = null;
                    }                    
                }

                public void InitializeController(BasePlayer player, int spectateIndex)
                {
                    CuiHelper.DestroyUi(this.player, SCUI_Panel);

                    controller = player.gameObject.AddComponent<Controller>();
                    ins.controllers.Add(controller);
                    controller.SetInitialTarget(this, spectateIndex);
                }
                
                public bool IsInUse() => controller != null || player != null;

                public void SetLinkController(Signage signage, DroppedItem computer)
                {
                    this.signage = signage;
                    this.computer = computer;
                }

                public void OnEntityTakeDamage(BaseCombatEntity entity, HitInfo info)
                {
                    if (controller != null)
                    {
                        if (entity == controller.player)
                        {
                            info.damageTypes = new DamageTypeList();
                            info.HitEntity = null;
                            info.HitMaterial = 0;
                            info.PointStart = Vector3.zero;                            
                        }
                        else
                        {
                            BaseMountable baseMountable = controller.player.GetMounted();
                            if (baseMountable != null && entity == baseMountable)
                            {
                                info.damageTypes = new DamageTypeList();
                                info.HitEntity = null;
                                info.HitMaterial = 0;
                                info.PointStart = Vector3.zero;
                            }
                        }
                    }                    
                }

                public void OnEntityDeath(BaseNetworkable networkable)
                {
                    CameraManager camera = networkable.GetComponent<CameraManager>();
                    if (camera != null && cameras.Contains(camera))
                        DestroyCamera(camera);

                    BuildingBlock buildingBlock = networkable.GetComponent<BuildingBlock>();
                    if (buildingBlock != null)
                    {
                        for (int i = cameras.Count - 1; i >=0; i--)
                        {
                            CameraManager camera1 = cameras.ElementAt(i);
                            if (camera1.parent == buildingBlock)
                                DestroyCamera(camera1);
                        }                        
                    }

                    Signage deadSignage = networkable.GetComponent<Signage>();
                    if (deadSignage != null && deadSignage == signage)
                        DestroySignage();                    
                }

                public void DestroyLink()
                {
                    CloseLink();

                    if (computer != null)
                    {
                        computer.DestroyItem();
                        if (!computer.IsDestroyed)
                            computer.Kill();
                        computer = null;
                    }
                    for (int i = cameras.Count - 1; i >= 0; i--)
                        UnityEngine.Object.Destroy(cameras.ElementAt(i));
                }

                public void DestroyCamera(CameraManager camera)
                {
                    cameras.Remove(camera);
                    ins.cameraManagers.Remove(camera);

                    if (controller != null)                    
                        controller.OnCameraDestroyed(camera);

                    UnityEngine.Object.Destroy(camera);
                }

                public void DestroySignage()
                {
                    DestroyComputer();                    

                    if (ins.storedData.signIds.Contains(signage.net.ID))
                        ins.storedData.signIds.Remove(signage.net.ID);

                    if (controller != null)
                        controller.OnSignageDestroyed();

                    signage = null;
                }   
                
                public void DestroyComputer()
                {
                    if (computer != null)
                    {
                        computer.DestroyItem();
                        if (!computer.IsDestroyed)
                            computer.Kill();
                        computer = null;
                    }

                }
            }
        }

        class ItemPlacement : MonoBehaviour
        {
            private BasePlayer player;
            private DroppedItem droppedItem;
            private BuildingBlock hitEntity = null;
            private bool isValidPlacement;

            private float placementDistance;

            private void Awake()
            {
                player = GetComponent<BasePlayer>();
                enabled = false;

                placementDistance = ins.configData.Camera.Distance;
                SpawnDroppedItem();
                player.ChatMessage(ins.msg("placeHelp1", player.userID));
            }

            private void FixedUpdate()
            {
                Item activeItem = player.GetActiveItem();
                if (activeItem == null || activeItem.info.itemid != 1300054961)
                    CancelPlacement();

                isValidPlacement = false;
                
                InputState input = player.serverInput;
                Vector3 eyePosition = player.transform.position + (Vector3.up * 1.8f);

                RaycastHit hit;
                if (Physics.Raycast(new Ray(player.transform.position + (Vector3.up * 1.8f), Quaternion.Euler(input.current.aimAngles) * Vector3.forward), out hit, placementDistance, layerPlcmnt))
                {
                    droppedItem.transform.position = hit.point + (-droppedItem.transform.right * 0.1f);
                    droppedItem.transform.rotation = Quaternion.LookRotation(eyePosition - droppedItem.transform.position, Vector3.up) * Quaternion.Euler(0, 90, 0);

                    isValidPlacement = hitEntity = hit.GetEntity()?.GetComponent<BuildingBlock>();                    
                }
                else
                {
                    droppedItem.transform.position = new Ray(eyePosition, Quaternion.Euler(input.current.aimAngles) * Vector3.forward).GetPoint(2);
                    droppedItem.transform.rotation = Quaternion.LookRotation(eyePosition - droppedItem.transform.position, Vector3.up) * Quaternion.Euler(0, 90, 0);
                }

                if (input.WasJustPressed(BUTTON.FIRE_PRIMARY))
                {
                    if (!isValidPlacement)
                    {
                        player.ChatMessage(ins.msg("placeHelp2", player.userID));
                        return;
                    }
                    else PlaceCamera();
                }
                else if (input.WasJustPressed(BUTTON.FIRE_SECONDARY))
                    CancelPlacement();
            }

            private void SpawnDroppedItem()
            {
                droppedItem = ins.SpawnDroppedItem(player.transform.position);                
                enabled = true;
            }
                        
            private void CancelPlacement()
            {
                enabled = false;
                droppedItem.DestroyItem();
                droppedItem.Kill();
                player.ChatMessage(ins.msg("placeHelp3", player.userID));
                Destroy(this);
            }

            private void PlaceCamera()
            {
                player.ChatMessage(ins.msg("placeHelp4", player.userID));
                player.inventory.containerBelt.Take(null, cameraId, 1);
                CameraManager camera = droppedItem.gameObject.AddComponent<CameraManager>();                
                Destroy(this);
            }

            public void OnPlayerDeath()
            {
                CancelPlacement();
                Destroy(this);
            }
        }

        class CameraManager : MonoBehaviour
        {            
            public DroppedItem entity { get; private set; }
            public BuildingBlock parent { get; private set; }
            public Vector3 baseRotation { get; set; }

            private void Awake()
            {
                entity = GetComponent<DroppedItem>();
                enabled = false;
                baseRotation = entity.transform.eulerAngles;

                OBB obb = entity.WorldSpaceBounds();
                List<BuildingBlock> list = Pool.GetList<BuildingBlock>();
                Vis.Entities<BuildingBlock>(obb.position, 0.5f + obb.extents.magnitude, list, 2097152, QueryTriggerInteraction.Collide);

                if (list.Count > 0)                
                    parent = list[0];                
                else
                {
                    print($"[ERROR] Unable to find parent block for security camera");
                    Destroy(this, 1f);
                }
                Pool.FreeList<BuildingBlock>(ref list);

                if (parent != null)
                {
                    ins.cameraManagers.Add(this);
                    linkManager.AddToLink(parent.GetBuilding(), this);
                }
            }  
            
            private void OnDestroy()
            {
                if (entity != null)
                {
                    entity.DestroyItem();
                    if (!entity.IsDestroyed)
                        entity.Kill();
                }
            }

            public void SetRotation(float[] rotation)
            {
                baseRotation = new Vector3(rotation[0], rotation[1], rotation[2]);
                entity.transform.rotation = Quaternion.Euler(baseRotation);
            }
            
            public CameraData GetCameraData() => new CameraData(this);
                       
            public class CameraData
            {
                public float[] position;
                public float[] baseRotation;

                public CameraData() { }

                public CameraData(CameraManager camera)
                {
                    position = new float[] { camera.entity.transform.position.x, camera.entity.transform.position.y, camera.entity.transform.position.z };
                    baseRotation = new float[] { camera.baseRotation.x, camera.baseRotation.y, camera.baseRotation.z };
                }
            }
        }

        class Controller : MonoBehaviour
        {
            public BasePlayer player { get; private set; }
            private BaseMountable mountPoint;
            
            private BuildingLinks.Link link;

            private CameraManager[] availableSources;
            private CameraManager spectateTarget;
            private int spectateIndex = 0;
                     
            private void Awake()
            {
                player = GetComponent<BasePlayer>();
                enabled = false;

                mountPoint = GameManager.server.CreateEntity(chairPrefab, player.transform.position) as BaseMountable;
                mountPoint.enableSaving = false;
                mountPoint.skinID = (ulong)1169930802;
                mountPoint.Spawn();   
            }

            private void OnDestroy()
            {
                if (mountPoint != null && !mountPoint.IsDestroyed)
                    mountPoint.Kill();

                if (!isUnloading)
                {                    
                    if (ins.controllers.Contains(this))
                        ins.controllers.Remove(this);
                }
            }

            private void FixedUpdate()
            {
                InputState input = player.serverInput;

                if (input.WasJustPressed(BUTTON.USE))
                {                    
                    FinishSpectating();
                    return;
                }                

                if (spectateTarget != null)
                {                   
                    Vector3 aimAngle = player.serverInput.current.aimAngles;
                    spectateTarget.entity.transform.rotation = Quaternion.Euler(aimAngle.x, aimAngle.y, 0) * Quaternion.Euler(0, 90, 0);                    
                }

                if (input.WasJustPressed(BUTTON.JUMP))
                    UpdateSpectateTarget(1);
                else if (input.WasJustPressed(BUTTON.DUCK))
                    UpdateSpectateTarget(-1);
            }

            public void BeginSpectating()
            {
                ins.LustyMap?.Call("DisableMaps", player);
                ins.restoreData.AddData(player);
                player.inventory.Strip();
                player.SetPlayerFlag(BasePlayer.PlayerFlags.Spectating, true);
                player.MountObject(mountPoint);                
            }

            public void FinishSpectating()
            {
                enabled = false;                
                player.SetPlayerFlag(BasePlayer.PlayerFlags.Spectating, false);
                player.DismountObject();
                player.EnsureDismounted();                
                ins.restoreData.RestorePlayer(player);
                ins.LustyMap?.Call("EnableMaps", player);
                CuiHelper.DestroyUi(player, SCUI_Overlay);
                link.CloseLink(true);
                Destroy(this);
            }

            public void SetInitialTarget(BuildingLinks.Link link, int spectateIndex)
            {
                this.link = link;
                GetSpectateTargets();

                if (availableSources.Length == 0)
                {
                    player.ChatMessage(ins.msg("noSources", player.userID));
                    Destroy(this);
                }
                else BeginSpectating();

                this.spectateIndex = spectateIndex;
                SetSpectateTarget();

                player.ChatMessage(ins.msg("controlInfo", player.userID));
                enabled = true;
            }
                       
            public void UpdateSpectateTarget(int index = 0)
            {
                spectateIndex = spectateIndex += index;

                if (spectateIndex > availableSources.Length - 1)
                    spectateIndex = 0;
                else if (spectateIndex < 0)
                    spectateIndex = availableSources.Length - 1;

                if (availableSources[spectateIndex] != spectateTarget)
                    SetSpectateTarget();               
            }

            public void SetSpectateTarget()
            {
                spectateTarget = availableSources[spectateIndex];
                mountPoint.transform.position = spectateTarget.entity.transform.position + (Vector3.down * 1.5f) + (-spectateTarget.entity.transform.right * 0.2f);
                mountPoint.transform.rotation = Quaternion.Euler(spectateTarget.baseRotation.x, spectateTarget.baseRotation.y, 0) * Quaternion.Euler(0, 270, 0);
                mountPoint.SendNetworkUpdate();
                CreateCameraOverlay();
            }

            private void GetSpectateTargets()
            {
                availableSources = link.cameras.Where(x => ins.IsValidSource(player, x)).ToArray();
                if (availableSources == null)
                    availableSources = new CameraManager[0];
            }

            private void CreateCameraOverlay()
            {
                if (!ins.configData.Camera.Overlay)
                    return;

                CuiElementContainer container = UI.Container("0 0 0 0", "0 0", "1 1", false, true, "Under");
                UI.Image(ref container, ins.GetImage("camoverlay"), "0 0", "1 1", true);
                UI.Panel(ref container, "0 0 0 0.4", "0.04 0.9", "0.18 0.94", true);
                UI.Label(ref container, "<color=red>REC</color>", 18, "0.04 0.9", "0.18 0.94", TextAnchor.MiddleCenter, true);

                UI.Panel(ref container, "0 0 0 0.4", "0.82 0.9", "0.96 0.94", true);
                UI.Label(ref container, string.Format(ins.msg("ui.Camera", player.userID), spectateIndex + 1), 18, "0.82 0.9", "0.96 0.94", TextAnchor.MiddleCenter, true);

                CuiHelper.DestroyUi(player, SCUI_Overlay);
                CuiHelper.AddUi(player, container);
            }

            public void OnCameraDestroyed(CameraManager camera)
            {
                GetSpectateTargets();

                if (availableSources.Length == 0)
                {
                    player.ChatMessage(ins.msg("noSources", player.userID));
                    FinishSpectating();                    
                    return;
                }

                if (camera == spectateTarget)
                {
                    player.ChatMessage(ins.msg("cameraDestroyed", player.userID));
                    UpdateSpectateTarget();
                }
            }            

            public void OnSignageDestroyed()
            {
                player.ChatMessage(ins.msg("controlDestroyed", player.userID));
                FinishSpectating();
            }             
        }
        #endregion

        #region UI
        const string SCUI_Panel = "SCUI_Panel";
        const string SCUI_Overlay = "SCUI_Overlay";

        public class UI
        {
            static public CuiElementContainer Container(string color, string aMin, string aMax, bool useCursor = false, bool isOverlay = false, string parent = "Overlay")
            {
                var NewElement = new CuiElementContainer()
                {
                    {
                        new CuiPanel
                        {
                            Image = {Color = color},
                            RectTransform = {AnchorMin = aMin, AnchorMax = aMax},
                            CursorEnabled = useCursor
                        },
                        new CuiElement().Parent = parent,
                        isOverlay ? SCUI_Overlay : SCUI_Panel
                    }
                };
                return NewElement;
            }

            static public void Panel(ref CuiElementContainer container, string color, string aMin, string aMax, bool isOverlay = false, bool cursor = false)
            {
                container.Add(new CuiPanel
                {
                    Image = { Color = color },
                    RectTransform = { AnchorMin = aMin, AnchorMax = aMax },
                    CursorEnabled = cursor
                },
                isOverlay ? SCUI_Overlay : SCUI_Panel);
            }

            static public void Label(ref CuiElementContainer container, string text, int size, string aMin, string aMax, TextAnchor align = TextAnchor.MiddleCenter, bool isOverlay = false)
            {
                container.Add(new CuiLabel
                {
                    Text = { FontSize = size, Align = align, Text = text },
                    RectTransform = { AnchorMin = aMin, AnchorMax = aMax }

                },
                isOverlay ? SCUI_Overlay : SCUI_Panel);
            }

            static public void Button(ref CuiElementContainer container, string color, string text, int size, string aMin, string aMax, string command, TextAnchor align = TextAnchor.MiddleCenter, bool isOverlay = false)
            {
                container.Add(new CuiButton
                {
                    Button = { Color = color, Command = command, FadeIn = 0f },
                    RectTransform = { AnchorMin = aMin, AnchorMax = aMax },
                    Text = { Text = text, FontSize = size, Align = align }
                },
                isOverlay ? SCUI_Overlay : SCUI_Panel);
            }
            static public void Image(ref CuiElementContainer container, string png, string aMin, string aMax, bool isOverlay = false)
            {
                container.Add(new CuiElement
                {
                    Name = CuiHelper.GetGuid(),
                    Parent = isOverlay ? SCUI_Overlay : SCUI_Panel,
                    Components =
                    {
                        new CuiRawImageComponent {Png = png },
                        new CuiRectTransformComponent { AnchorMin = aMin, AnchorMax = aMax }
                    }
                });
            }

            public static string Color(string hexColor, float alpha)
            {
                if (hexColor.StartsWith("#"))
                    hexColor = hexColor.Substring(1);
                int red = int.Parse(hexColor.Substring(0, 2), NumberStyles.AllowHexSpecifier);
                int green = int.Parse(hexColor.Substring(2, 2), NumberStyles.AllowHexSpecifier);
                int blue = int.Parse(hexColor.Substring(4, 2), NumberStyles.AllowHexSpecifier);
                return $"{(double)red / 255} {(double)green / 255} {(double)blue / 255} {alpha}";
            }
        }
        #endregion

        #region UI Generation
        enum Colors { Background, Panel, Button, Selected }
        private void DisplayToPlayer(BasePlayer player, int page = 0)
        {
            CuiElementContainer container = null;            
            CameraManager[] cameras = linkManager.GetCamerasOf(player).Where(x => IsValidSource(player, x)).ToArray();

            if (cameras == null || cameras.Length == 0)
            {
                container = UI.Container(uiColors[Colors.Background], "0.4 0.4", "0.6 0.6", true);
                UI.Label(ref container, msg("ui.Title", player.userID), 25, "0.05 0.7", "0.95 1");
                UI.Label(ref container, msg("ui.NoCameras", player.userID), 12, "0.05 0.5", "0.95 0.7");
                UI.Button(ref container, uiColors[Colors.Button], msg("ui.Close", player.userID), 12, "0.25 0.2", "0.75 0.45", "scui.close");
            }
            else
            {
                container = UI.Container(uiColors[Colors.Background], "0.35 0.15", "0.65 0.95", true);
                UI.Label(ref container, msg("ui.Title", player.userID), 25, "0.05 0.9", "0.95 1");
                UI.Button(ref container, uiColors[Colors.Selected], "✖", 15, "0.91 0.95", "0.99 0.99", "scui.close");
                UI.Label(ref container, msg("ui.Information", player.userID), 12, "0.05 0.85", "0.95 0.95");
                int count = 0;
                int startAt = page * 20;
                for (int i = startAt; i < (startAt + 20 > cameras.Length ? cameras.Length : startAt + 20); i++)
                {
                    CameraManager camera = cameras.ElementAt(i);
                    UI.Panel(ref container, uiColors[Colors.Panel], $"0.04 {(0.81f - (count * 0.04f)) + 0.005f}", $"0.96 {(0.85f - (count * 0.04f)) - 0.005f}");
                    UI.Label(ref container, string.Format(msg("ui.Camera", player.userID), count + 1), 11, $"0.05 {0.81f - (count * 0.04f) + 0.005f}", $"0.31 {0.85f - (count * 0.04f) - 0.005f}", TextAnchor.MiddleLeft);
                    
                    UI.Button(ref container, uiColors[Colors.Button], msg("ui.Control", player.userID), 11, $"0.76 {0.81f - (count * 0.04f) + 0.005f}", $"0.97 {0.85f - (count * 0.04f) - 0.005f}", $"scui.control {i}");

                    count++;
                }

                int totalPages = cameras.Length / 20;

                UI.Button(ref container, uiColors[Colors.Button], msg("ui.Back", player.userID), 11, "0.1 0.01", "0.35 0.04", page > 0 ? $"scui.changepage {page - 1}" : "");
                UI.Label(ref container, string.Format(msg("ui.Page", player.userID), page + 1, totalPages + 1), 11, "0.35 0.01", "0.65 0.04");
                UI.Button(ref container, uiColors[Colors.Button], msg("ui.Next", player.userID), 11, "0.65 0.01", "0.9 0.04", page + 1 <= totalPages ? $"scui.changepage {page + 1}" : "");
            }

            CuiHelper.DestroyUi(player, SCUI_Panel);
            CuiHelper.AddUi(player, container);
        }
        #endregion
                
        #region UI Commands 
       
        [ConsoleCommand("scui.changepage")]
        private void ccmdChangePage(ConsoleSystem.Arg arg)
        {
            BasePlayer player = arg.Connection.player as BasePlayer;
            if (player == null)
                return;

            DisplayToPlayer(player, arg.GetInt(0));
        }
               
        [ConsoleCommand("scui.control")]
        private void ccmdControl(ConsoleSystem.Arg arg)
        {
            BasePlayer player = arg.Connection.player as BasePlayer;
            if (player == null)
                return;

            if (player.GetComponent<Controller>())
                return;

            BuildingLinks.Link link = linkManager.GetLinkOf(player);
            if (link != null)
            {
                link.InitializeController(player, arg.GetInt(0));                
                CuiHelper.DestroyUi(player, SCUI_Panel);
            }
        }

        [ConsoleCommand("scui.close")]
        private void ccmdCloseUI(ConsoleSystem.Arg arg)
        {
            BasePlayer player = arg.Connection.player as BasePlayer;
            if (player == null)
                return;

            BuildingLinks.Link link = linkManager.GetLinkOf(player);
            if (link != null)            
                link.CloseLink();            

            CuiHelper.DestroyUi(player, SCUI_Panel);
        }
        #endregion

        #region Commands
        [ChatCommand("sc")]
        private void cmdSC(BasePlayer player, string command, string[] args)
        {
            if (!permission.UserHasPermission(player.UserIDString, permUse)) return;
            if (args.Length == 0)
            {
                SendReply(player, $"<color=#ce422b>{Title}</color><color=#939393>  v{Version}  -</color> <color=#ce422b>{Author} @ www.chaoscode.io</color>");
                SendReply(player, msg("help2", player.userID));
                SendReply(player, msg("help3", player.userID));
                SendReply(player, msg("help4", player.userID));
                SendReply(player, msg("help5", player.userID));
                return;
            }

            if (!player.IsBuildingAuthed())
            {
                SendReply(player, msg("noAuth", player.userID));
                return;
            }

            if (args[0].ToLower() == "controller")
            {
                Signage signage = FindEntityFromRay(player) as Signage;
                if (signage == null)
                {
                    SendReply(player, msg("noSign", player.userID));
                    return;
                }

                if (signage.OwnerID != player.userID)
                {
                    if (configData.Camera.Friends && !IsFriendlyPlayer(signage.OwnerID, player.userID))
                    {
                        SendReply(player, msg("notOwner", player.userID));
                        return;
                    }
                }

                BuildingLinks.Link link = null;

                if (args.Length >= 2 && args[1].ToLower() == "remove")
                {
                    link = linkManager.GetLinkOf(signage);
                    if (link == null || !storedData.signIds.Contains(signage.net.ID))
                    {
                        SendReply(player, msg("notController", player.userID));
                        return;
                    }
                    
                    link.DestroySignage();
                    SaveData();

                    SendReply(player, msg("removedController", player.userID));
                    player.GiveItem(ItemManager.CreateByItemID(computerId), BaseEntity.GiveItemReason.PickedUp);
                    return;
                }

                BuildingManager.Building building = GetBuilding(signage);

                if (building == null)
                {
                    SendReply(player, msg("noBuilding", player.userID));
                    return;
                }

                link = linkManager.GetLinkOf(building);
                if (link != null && link.signage != null)
                {
                    SendReply(player, msg("hasController", player.userID));
                    return;
                }

                if (storedData.signIds.Contains(signage.net.ID))
                {
                    SendReply(player, msg("isController", player.userID));
                    return;
                }

                if (configData.Control.RequireComputer)
                {
                    if (player.inventory.GetAmount(computerId) < 1)
                    {
                        SendReply(player, msg("needComputer", player.userID));
                        return;
                    }
                    player.inventory.Take(null, computerId, 1);
                }

                storedData.signIds.Add(signage.net.ID);

                InitializeSign(signage);

                SaveData();
                SendReply(player, msg("controllerSuccess", player.userID));
                return;
            }
                        
            switch (args[0].ToLower())
            {
                case "add":
                    {
                        Item activeItem = player.GetActiveItem();
                        if (activeIte
// ... [Code preview truncated due to length. Full source in attached file] ...

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