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

FREE SecurityCameras : 0.2.29 0.2.29

Нет прав для скачивания
C#:
//Requires: RustNET
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
using Oxide.Core.Configuration;
using Oxide.Game.Rust.Cui;
using UnityEngine;
using System.Linq;
using Rust;
using Facepunch;
using Network;
namespace Oxide.Plugins {
    [Info("SecurityCameras", "k1lly0u", "0.2.29")]
    [Description("Deploy security cameras around your base and view them by accessing a RustNET terminal")]
    class SecurityCameras : RustPlugin {
#region Fields
        private StoredData storedData;
        private DynamicConfigFile data;
        private static SecurityCameras ins;
        private static LinkManager linkManager;
        private static int layerPlcmnt;
        private List<CameraManager> cameraManagers = new List<CameraManager>();
        private bool wipeDetected;
        private bool isInitialized;
        const string permUse = "securitycameras.use";
        const string permIgnore = "securitycameras.ignorelimit";
        const string permPublic = "securitycameras.public";
        const string SCUI_Overlay = "SCUI_Overlay";
        const string CHAIR_PREFAB = "assets/prefabs/deployable/chair/chair.deployed.prefab";
        const int CAMERA_ID = 634478325;
#endregion
#region Oxide Hooks
        private void Loaded() {
            permission.RegisterPermission(permUse, this);
            permission.RegisterPermission(permIgnore, this);
            permission.RegisterPermission(permPublic, 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("RustNET/cameras");
            linkManager = new LinkManager();
        }
        private void OnServerInitialized() {
            ins = this;
            LoadData();
            LoadDefaultImages();
            layerPlcmnt = LayerMask.GetMask("Construction", "Default", "Deployed", "World", "Terrain");
            if (wipeDetected) {
                storedData = new StoredData();
                SaveData();
            }
            InvokeHandler.Invoke(ServerMgr.Instance, InitializeAllLinks, 10f);
            RustNET.RegisterModule(Title, this);
        }
        private void OnPlayerDisconnected(BasePlayer player) {
            Controller controller = player.GetComponent<Controller>();
            if (controller != null) {
                LinkManager.CameraLink link = linkManager.GetLinkOf(controller);
                if (link != null) link.CloseLink(controller);
            }
        }
        private object OnPlayerCommand(ConsoleSystem.Arg arg) {
            BasePlayer player = arg.Player();
            if (player != null && player.GetComponent<Controller>()) return false;
            return null;
        }
        private object OnPlayerTick(BasePlayer player, PlayerTick msg, bool wasPlayerStalled) {
            Controller controller = player.GetComponent<Controller>();
            if (controller != null) return false;
            return null;
        }
        private void OnEntityKill(BaseNetworkable networkable) {
            if (networkable != null && (networkable is BuildingBlock || networkable is DroppedItem)) linkManager.OnEntityDeath(networkable);
        }
        private void OnEntityTakeDamage(BaseCombatEntity entity, HitInfo info) {
            if (entity == null || info == null) return;
            if (entity is BasePlayer) {
                if (entity.GetComponent<Controller>()) {
                    info.damageTypes = new DamageTypeList();
                    info.HitEntity = null;
                    info.HitMaterial = 0;
                    info.PointStart = Vector3.zero;
                }
            }
            else if (entity is BaseMountable) linkManager.OnEntityTakeDamage(entity, info);
        }
        private void OnNewSave(string filename) => wipeDetected = true;
        private void OnServerSave() {
            if (isInitialized) SaveData();
        }
        private object CanDismountEntity(BasePlayer player, BaseMountable mountable) {
            Controller controller = player.GetComponent<Controller>();
            if (controller != null) return false;
            return null;
        }
        private void Unload() {
            if (InvokeHandler.IsInvoking(ServerMgr.Instance, InitializeAllLinks)) InvokeHandler.CancelInvoke(ServerMgr.Instance, InitializeAllLinks);
            if (!ServerMgr.Instance.Restarting) SaveData();
            foreach (BasePlayer player in BasePlayer.activePlayerList) CuiHelper.DestroyUi(player, SCUI_Overlay);
            linkManager.DestroyAllLinks(true);
            for (int i = cameraManagers.Count - 1; i >= 0; i--) cameraManagers[i].Destroy();
            ins = null;
            linkManager = null;
        }
#endregion
#region Functions
        private bool CanPlaceItem(BasePlayer player, bool ignoreRestriction) {
            int cameraCount = 0;
            BuildingManager.Building building = player.GetBuildingPrivilege()?.GetBuilding();
            if (building != null) {
                RustNET.LinkManager.Link buildingLink = RustNET.linkManager.GetLinkOf(building);
                if (buildingLink == null && !ignoreRestriction) {
                    SendReply(player, msg("Error.NoTerminal", player.userID));
                    return false;
                }
                cameraCount = linkManager.GetLinkOf(building)?.Managers.Count ?? 0;
            }
            else {
                if (!ignoreRestriction) {
                    SendReply(player, msg("Error.NoBuildingPrivilege", player.userID));
                    return false;
                }
            }
            int cameraLimit = GetMaxCameras(player.userID);
            if (!permission.UserHasPermission(player.UserIDString, permIgnore) && cameraCount >= cameraLimit) {
                SendReply(player, msg("Error.Limit", player.userID));
                return false;
            }
            return true;
        }
        private void InitializeAllLinks() {
            for (int i = 0; i < storedData.cameraData.Length; i++) {
                CameraManager.CameraData cameraData = storedData.cameraData.ElementAt(i);
                int terminalId = cameraData.terminalId;
                BuildingManager.Building building = null;
                RustNET.LinkManager.Link link = RustNET.linkManager.GetLinkOf(cameraData.terminalId);
                if (link == null || !link.IsPublicLink) {
                    building = RustNET.GetBuilding(new Vector3(cameraData.position[0], cameraData.position[1], cameraData.position[2]), 0.5f);
                    if (building == null) continue;
                    else terminalId = RustNET.linkManager.GetLinkOf(building)?.terminal?.TerminalID ?? 0;
                }
                LinkManager.CameraLink cameraLink = linkManager.GetLinkOf(terminalId);
                if (cameraLink == null) cameraLink = new LinkManager.CameraLink(terminalId, building, cameraData);
                else cameraLink.AddCameraToLink(cameraData);
            }
            isInitialized = true;
        }
        private CameraManager InitializeCamera(CameraManager.CameraData cameraData, int terminalId) {
            CameraManager camera = RustNET.SpawnDroppedItem(CAMERA_ID, new Vector3(cameraData.position[0], cameraData.position[1], cameraData.position[2]), new Vector3(cameraData.baseRotation[0], cameraData.baseRotation[1], cameraData.baseRotation[2])).gameObject.AddComponent<CameraManager>();
            camera.SetRotation(new float[] {
                cameraData.baseRotation[0], cameraData.baseRotation[1], cameraData.baseRotation[2]
            }
            );
            camera.TerminalID = terminalId;
            camera.CameraName = cameraData.cameraName;
            return camera;
        }
        private void InitializeCamera(BasePlayer player, DroppedItem droppedItem) {
            BuildingManager.Building building = RustNET.GetBuilding(droppedItem.transform.position, 0.5f);
            if (building == null) {
                droppedItem.DestroyItem();
                droppedItem.Kill();
                player.GiveItem(ItemManager.CreateByItemID(CAMERA_ID), BaseEntity.GiveItemReason.PickedUp);
                SendReply(player, msg("Error.InvalidPlacement", player.userID));
                return;
            }
            int terminalId = RustNET.linkManager.GetLinkOf(building)?.terminal?.TerminalID ?? 0;
            CameraManager camera = RustNET.SpawnDroppedItem(CAMERA_ID, droppedItem.transform.position, droppedItem.transform.eulerAngles).gameObject.AddComponent<CameraManager>();
            camera.SetRotation(new float[] {
                droppedItem.transform.eulerAngles.x, droppedItem.transform.eulerAngles.y, droppedItem.transform.eulerAngles.z
            }
            );
            camera.TerminalID = terminalId;
            LinkManager.CameraLink cameraLink = linkManager.GetLinkOf(terminalId);
            if (cameraLink == null) cameraLink = new LinkManager.CameraLink(terminalId, building, camera);
            else cameraLink.AddCameraToLink(camera);
        }
        private void InitializeCamera(BasePlayer player, DroppedItem droppedItem, int terminalId) {
            CameraManager camera = RustNET.SpawnDroppedItem(CAMERA_ID, droppedItem.transform.position, droppedItem.transform.eulerAngles).gameObject.AddComponent<CameraManager>();
            camera.SetRotation(new float[] {
                droppedItem.transform.eulerAngles.x, droppedItem.transform.eulerAngles.y, droppedItem.transform.eulerAngles.z
            }
            );
            camera.TerminalID = terminalId;
            LinkManager.CameraLink cameraLink = linkManager.GetLinkOf(terminalId);
            if (cameraLink == null) cameraLink = new LinkManager.CameraLink(terminalId, null, camera);
            else cameraLink.AddCameraToLink(camera);
        }
        private object CanSpawnInZone(DroppedItem droppedItem) {
            if (droppedItem.GetComponent<CameraManager>()) return true;
            return null;
        }
        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 RustNET Integration
        private void DestroyAllLinks() => linkManager.DestroyAllLinks(true);
        private void OnTerminalCreated(RustNET.TerminalManager terminal) {
            BuildingManager.Building building = terminal.ParentEntity?.GetBuilding();
            if (building == null) return;
            for (int i = cameraManagers.Count - 1; i >= 0; i--) {
                CameraManager camera = cameraManagers[i];
                if (camera.Parent?.GetBuilding() == building) {
                    LinkManager.CameraLink link = linkManager.GetLinkOf(terminal.TerminalID);
                    if (link == null) link = new LinkManager.CameraLink(terminal.TerminalID, building, camera);
                    else link.AddCameraToLink(camera);
                }
            }
        }
        private void OnTerminalRemoved(int terminalId) {
            LinkManager.CameraLink link = linkManager.GetLinkOf(terminalId);
            if (link != null) {
                for (int i = cameraManagers.Count - 1; i >= 0; i--) {
                    CameraManager camera = cameraManagers[i];
                    if (camera.TerminalID == terminalId) camera.TerminalID = 0;
                }
                linkManager.links.Remove(link);
            }
        }
        private void OnLinkShutdown(int terminalId) {
            LinkManager.CameraLink link = linkManager.GetLinkOf(terminalId);
            if (link != null) link.OnLinkTerminated(false);
        }
        private void OnLinkDestroyed(int terminalId) {
            LinkManager.CameraLink link = linkManager.GetLinkOf(terminalId);
            if (link != null) link.OnLinkTerminated(true);
        }
        private CameraManager[] GetAvailableCameras(int terminalId) {
            LinkManager.CameraLink link = linkManager.GetLinkOf(terminalId);
            if (link != null) return link.Managers.Where(x => x != null && x.Camera != null).ToArray();
            return new CameraManager[0];
        }
        private void InitializeController(BasePlayer player, uint managerId, int terminalId) {
            LinkManager.CameraLink link = linkManager.GetLinkOf(terminalId);
            if (link != null) link.InitiateLink(player, managerId);
        }
        private string GetHelpString(ulong playerId, bool title) {
            if (title) return msg("UI.Help.Title", playerId);
            else {
                string message = msg("UI.Help", playerId);
                if (permission.UserHasPermission(playerId.ToString(), permPublic)) message += msg("UI.Help.Public", playerId);
                return message;
            }
        }
        private bool AllowPublicAccess() => true;
#endregion
#region Components
        private class LinkManager {
            public List<CameraLink> links = new List<CameraLink>();
            public CameraLink GetLinkOf(BuildingManager.Building building) => links.Find(x => x.Building == building) ?? null;
            public CameraLink GetLinkOf(CameraManager camera) => links.Find(x => x.Managers.Contains(camera)) ?? null;
            public CameraLink GetLinkOf(Controller controller) => links.Find(x => x.Controllers.Contains(controller)) ?? null;
            public CameraLink GetLinkOf(int terminalId) => links.Find(x => x.TerminalID == terminalId) ?? null;
            public CameraLink GetLinkOf(DroppedItem camera) {
                CameraManager component = camera.GetComponent<CameraManager>();
                if (component == null) return null;
                return GetLinkOf(component);
            }
            public void OnEntityTakeDamage(BaseCombatEntity entity, HitInfo info) {
                for (int i = links.Count - 1; i >= 0; i--) links.ElementAt(i).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(bool shutdown) {
                foreach (CameraLink link in links) {
                    link.OnLinkTerminated(false);
                    if (shutdown) link.DestroyCameraManagers();
                }
            }
            public class CameraLink {
                public int TerminalID {
                    get;
                    set;
                }
                public BuildingManager.Building Building {
                    get;
                    private set;
                }
                public List<Controller> Controllers {
                    get;
                    private set;
                }
                public List<CameraManager> Managers {
                    get;
                    private set;
                }
                public CameraLink() {
                }
                public CameraLink(int terminalId, BuildingManager.Building building, CameraManager camera) {
                    this.TerminalID = terminalId;
                    this.Building = building;
                    this.Controllers = new List<Controller>();
                    this.Managers = new List<CameraManager>();
                    AddCameraToLink(camera);
                    linkManager.links.Add(this);
                }
                public CameraLink(int terminalId, BuildingManager.Building building, CameraManager.CameraData cameraData) {
                    this.TerminalID = terminalId;
                    this.Building = building;
                    this.Controllers = new List<Controller>();
                    this.Managers = new List<CameraManager>();
                    AddCameraToLink(cameraData);
                    linkManager.links.Add(this);
                }
                public void AddCameraToLink(CameraManager camera) {
                    Managers.Add(camera);
                    if (!ins.cameraManagers.Contains(camera)) ins.cameraManagers.Add(camera);
                }
                public void AddCameraToLink(CameraManager.CameraData cameraData) {
                    CameraManager camera = ins.InitializeCamera(cameraData, TerminalID);
                    Managers.Add(camera);
                    if (!ins.cameraManagers.Contains(camera)) ins.cameraManagers.Add(camera);
                }
                public void InitiateLink(BasePlayer player, uint managerId) {
                    CameraManager manager = Managers.FirstOrDefault(x => x.Camera.net.ID == managerId);
                    if (manager != null) {
                        player.inventory.crafting.CancelAll(true);
                        Controller controller = player.gameObject.AddComponent<Controller>();
                        Controllers.Add(controller);
                        controller.InitiateLink(TerminalID);
                        controller.SetCameraLink(this);
                        controller.SetSpectateTarget(Managers.IndexOf(manager));
                    }
                }
                public void CloseLink(Controller controller, bool isDead = false) {
                    if (controller != null) {
                        Controllers.Remove(controller);
                        controller.FinishSpectating(isDead);
                    }
                }
                public void OnEntityTakeDamage(BaseCombatEntity entity, HitInfo info) {
                    foreach (Controller controller in Controllers) {
                        if (controller != null && entity == controller.mountPoint) {
                            info.damageTypes = new DamageTypeList();
                            info.HitEntity = null;
                            info.HitMaterial = 0;
                            info.PointStart = Vector3.zero;
                        }
                    }
                }
                public void OnEntityDeath(BaseNetworkable networkable) {
                    CameraManager manager = networkable.GetComponent<CameraManager>();
                    if (manager != null && Managers.Contains(manager)) {
                        if (manager.Controller != null) {
                            manager.Controller.player.ChatMessage(ins.msg("Warning.CameraDestroyed", manager.Controller.player.userID));
                            CloseLink(manager.Controller);
                        }
                        OnCameraDestroyed(manager);
                        return;
                    }
                    BuildingBlock buildingBlock = networkable.GetComponent<BuildingBlock>();
                    if (buildingBlock != null) {
                        for (int i = Managers.Count - 1; i >= 0; i--) {
                            CameraManager camera = Managers.ElementAt(i);
                            if (camera.Parent == buildingBlock) {
                                if (camera.Controller != null) {
                                    camera.Controller.player.ChatMessage(ins.msg("Warning.CameraDestroyed", camera.Controller.player.userID));
                                    CloseLink(camera.Controller);
                                }
                                OnCameraDestroyed(camera);
                            }
                        }
                    }
                }
                public void OnLinkTerminated(bool isDestroyed) {
                    for (int i = Controllers.Count - 1; i >= 0; i--) {
                        Controller controller = Controllers.ElementAt(i);
                        controller.player.ChatMessage(isDestroyed ? ins.msg("Warning.TerminalDestroyed", controller.player.userID) : ins.msg("Warning.TerminalShutdown", controller.player.userID));
                        CloseLink(controller);
                    }
                }
                public void OnCameraDestroyed(CameraManager manager) {
                    ins.cameraManagers.Remove(manager);
                    Managers.Remove(manager);
                    UnityEngine.Object.Destroy(manager);
                    if (Managers.Count == 0) {
                        linkManager.links.Remove(this);
                        return;
                    }
                    for (int i = Managers.Count - 1; i >= 0; i--) {
                        CameraManager m = Managers.ElementAt(i);
                        if (m == null || m.Camera == null) Managers.RemoveAt(i);
                    }
                }
                public void DestroyCameraManagers() {
                    foreach (CameraManager manager in Managers) UnityEngine.Object.Destroy(manager);
                    Managers.Clear();
                }
            }
        }
        class CameraManager : MonoBehaviour {
            public DroppedItem Camera {
                get;
                private set;
            }
            public Controller Controller {
                get;
                private set;
            }
            public BuildingBlock Parent {
                get;
                private set;
            }
            public Vector3 BaseRotation {
                get;
                set;
            }
            public int TerminalID {
                get;
                set;
            }
            public string CameraName {
                get;
                set;
            }
            private void Awake() {
                Camera = GetComponent<DroppedItem>();
                enabled = false;
                BaseRotation = Camera.transform.eulerAngles;
                OBB obb = Camera.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];
                    ins.cameraManagers.Add(this);
                    TerminalID = RustNET.linkManager.GetLinkOf(Parent.GetBuilding())?.terminal?.TerminalID ?? 0;
                }
                Pool.FreeList<BuildingBlock>(ref list);
            }
            private void OnDestroy() {
                if (Camera != null) {
                    Camera.DestroyItem();
                    if (!Camera.IsDestroyed) Camera.Kill();
                }
            }
            public void Destroy() => Destroy(this);
            public void SetRotation(float[] rotation) {
                BaseRotation = new Vector3(rotation[0], rotation[1], rotation[2]);
                Camera.transform.rotation = Quaternion.Euler(BaseRotation);
            }
            public void SetController(Controller controller) => this.Controller = controller;
            public CameraData GetCameraData() => new CameraData(this);
            public class CameraData {
                public float[] position;
                public float[] baseRotation;
                public string cameraName;
                public int terminalId;
                public CameraData() {
                }
                public CameraData(CameraManager camera) {
                    position = new float[] {
                        camera.Camera.transform.position.x, camera.Camera.transform.position.y, camera.Camera.transform.position.z
                    }
                    ;
                    baseRotation = new float[] {
                        camera.BaseRotation.x, camera.BaseRotation.y, camera.BaseRotation.z
                    }
                    ;
                    cameraName = camera.CameraName;
                    terminalId = camera.TerminalID;
                }
            }
        }
        class Controller : RustNET.Controller {
            public CameraManager manager {
                get;
                private set;
            }
            public BaseMountable mountPoint {
                get;
                private set;
            }
            private LinkManager.CameraLink link;
            private int spectateIndex;
            private bool switchingTargets;
            private bool canCyle;
            public override void Awake() {
                base.Awake();
                enabled = false;
                canCyle = ins.configData.Camera.CanCycle;
                mountPoint = GameManager.server.CreateEntity(CHAIR_PREFAB, player.transform.position) as BaseMountable;
                mountPoint.enableSaving = false;
                mountPoint.skinID = (ulong)1169930802;
                // 1311472987
                mountPoint.isMobile = true;
                mountPoint.Spawn();
                Destroy(mountPoint.GetComponent<DestroyOnGroundMissing>());
                Destroy(mountPoint.GetComponent<GroundWatch>());
                Destroy(mountPoint.GetComponent<MeshCollider>());
            }
            public override void OnDestroy() {
                player.SetPlayerFlag(BasePlayer.PlayerFlags.Spectating, false);
                player.DismountObject();
                player.EnsureDismounted();
                if (mountPoint != null && !mountPoint.IsDestroyed) mountPoint.Kill();
                base.OnDestroy();
            }
            private void Update() {
                if (player == null || player.serverInput == null || switchingTargets) return;
                InputState input = player.serverInput;
                if (manager.Controller == this) {
                    Vector3 aimAngle = player.serverInput.current.aimAngles;
                    manager.Camera.transform.rotation = Quaternion.Euler(aimAngle.x, aimAngle.y, 0) * Quaternion.Euler(0, 90, 0);
                }
                if (input.WasJustPressed(BUTTON.USE)) {
                    enabled = false;
                    link.CloseLink(this);
                }
                else {
                    if (canCyle) {
                        if (input.WasJustPressed(BUTTON.JUMP)) UpdateSpectateTarget(1);
                        else if (input.WasJustPressed(BUTTON.DUCK)) UpdateSpectateTarget(-1);
                    }
                }
            }
            public void SetCameraLink(LinkManager.CameraLink link) {
                this.link = link;
                BeginSpectating();
            }
            public void BeginSpectating() {
                RustNET.StripInventory(player);
                player.SetPlayerFlag(BasePlayer.PlayerFlags.Spectating, true);
                player.MountObject(mountPoint);
                if (Net.sv.write.Start()) {
                    Net.sv.write.PacketID(Message.Type.EntityDestroy);
                    Net.sv.write.EntityID(player.net.ID);
                    Net.sv.write.UInt8((byte)BaseNetworkable.DestroyMode.None);
                    Net.sv.write.Send(new SendInfo(player.net.group.subscribers.Where(x => x.userid != player.userID).ToList()));
                }
                player.limitNetworking = true;
                player.syncPosition = false;
                if (canCyle) player.ChatMessage(ins.msg("Help.ControlInfo", player.userID));
                else player.ChatMessage(ins.msg("Help.ControlInfo.NoCycle", player.userID));
            }
            public void FinishSpectating(bool isDead) {
                enabled = false;
                player.SetPlayerFlag(BasePlayer.PlayerFlags.Spectating, false);
                player.limitNetworking = false;
                player.syncPosition = true;
                InvokeHandler.CancelInvoke(player, UpdateNetworkGroup);
                player.DismountObject();
                player.EnsureDismounted();
                CuiHelper.DestroyUi(player, SCUI_Overlay);
                if (!isDead) Destroy(this);
            }
            public void SetSpectateTarget(int spectateIndex) {
                this.spectateIndex = spectateIndex;
                manager = link.Managers[spectateIndex];
                enabled = true;
                mountPoint.transform.position = manager.Camera.transform.position + (Vector3.down * 1.5f) + (-manager.Camera.transform.right * 0.2f);
                mountPoint.transform.rotation = Quaternion.Euler(manager.BaseRotation.x, manager.BaseRotation.y, 0) * Quaternion.Euler(0, 270, 0);
                mountPoint.SendNetworkUpdate();
                UpdateNetworkGroup();
                if (manager.Controller == null) manager.SetController(this);
                else player.ChatMessage(ins.msg("Warning.InUse", player.userID));
                CreateCameraOverlay();
            }
            private void UpdateNetworkGroup() {
                Network.Visibility.Group group = Net.sv.visibility.GetGroup(manager.Camera.transform.position);
                if (mountPoint.net.group != group) mountPoint.net.SwitchGroup(group);
                if (player.net.group != group) player.net.SwitchGroup(group);
            }
            public void UpdateSpectateTarget(int index = 0) {
                switchingTargets = true;
                player.Invoke(() => switchingTargets = false, 0.25f);
                int newIndex = spectateIndex + index;
                if (newIndex > link.Managers.Count - 1) newIndex = 0;
                else if (newIndex < 0) newIndex = link.Managers.Count - 1;
                if (spectateIndex == newIndex) return;
                if (manager.Controller == this) manager.SetController(null);
                manager = null;
                SetSpectateTarget(newIndex);
            }
            public override void OnPlayerDeath(HitInfo info) {
                enabled = false;
                link.CloseLink(this, true);
                base.OnPlayerDeath(info);
            }
            private void CreateCameraOverlay() {
                if (!ins.configData.Camera.Overlay) return;
                CuiElementContainer container = RustNET.UI.Container("0 0 0 0", "0 0", "1 1", false, "Under", SCUI_Overlay);
                RustNET.UI.Image(ref container, ins.GetImage("camoverlay"), "0 0", "1 1", SCUI_Overlay);
                RustNET.UI.Panel(ref container, "0 0 0 0.4", "0.04 0.9", "0.18 0.94", SCUI_Overlay);
                RustNET.UI.Label(ref container, "<color=red>REC</color>", 18, "0.04 0.9", "0.18 0.94", TextAnchor.MiddleCenter, SCUI_Overlay);
                RustNET.UI.Panel(ref container, "0 0 0 0.4", "0.82 0.9", "0.96 0.94", SCUI_Overlay);
                RustNET.UI.Label(ref container, string.IsNullOrEmpty(manager.CameraName) ? string.Format(ins.msg("UI.CameraName", player.userID), spectateIndex + 1) : manager.CameraName, 18, "0.82 0.9", "0.96 0.94", TextAnchor.MiddleCenter, SCUI_Overlay);
                CuiHelper.DestroyUi(player, SCUI_Overlay);
                CuiHelper.AddUi(player, container);
            }
        }
#endregion
#region UI
        private void CreateConsoleWindow(BasePlayer player, int terminalId, int page) {
            CuiElementContainer container = RustNET.ins.GetBaseContainer(player, terminalId, Title);
            CameraManager[] entityIds = GetAvailableCameras(terminalId);
            RustNET.UI.Panel(ref container, RustNET.uiColors[RustNET.Colors.Panel], "0.04 0.765", "0.96 0.8");
            RustNET.UI.Label(ref container, msg("UI.Select.Camera", player.userID), 12, "0.05 0.765", "0.5 0.8", TextAnchor.MiddleLeft);
            RustNET.UI.Button(ref container, RustNET.uiColors[RustNET.Colors.Button], RustNET.msg("UI.MainMenu", player.userID), 11, "0.82 0.765", "0.96 0.8", $"rustnet.changepage {terminalId}");
            if (entityIds == null || entityIds.Length == 0) RustNET.UI.Label(ref container, msg("UI.NoCameras", player.userID), 12, "0.05 0.5", "0.95 0.7");
            else {
                int count = 0;
                int startAt = page * 18;
                for (int i = startAt; i < (startAt + 18 > entityIds.Length ? entityIds.Length : startAt + 18);
                i++) {
                    CameraManager manager = entityIds.ElementAt(i);
                    RustNET.UI.Panel(ref container, RustNET.uiColors[RustNET.Colors.Panel], $"0.04 {(0.725f - (count * 0.04f))}", $"0.96 {(0.755f - (count * 0.04f))}");
                    RustNET.UI.Label(ref container, string.IsNullOrEmpty(manager.CameraName) ? string.Format(msg("UI.Camera", player.userID), i + 1) : $"> {manager.CameraName}", 11, $"0.05 {0.725f - (count * 0.04f)}", $"0.31 {0.755f - (count * 0.04f)}", TextAnchor.MiddleLeft);
                    RustNET.UI.Button(ref container, RustNET.uiColors[RustNET.Colors.Button], RustNET.msg("UI.Control", player.userID), 11, $"0.76 {0.725f - (count * 0.04f)}", $"0.96 {0.755f - (count * 0.04f)}", $"securitycameras.control {manager.Camera.net.ID} {terminalId}");
                    count++;
                }
                int totalPages = entityIds.Length / 18;
                RustNET.UI.Button(ref container, RustNET.uiColors[RustNET.Colors.Button], RustNET.msg("UI.Back", player.userID), 11, "0.3 0.01", "0.44 0.04", page > 0 ? $"rustnet.changepage {terminalId} {Title} {page - 1}" : "");
                RustNET.UI.Label(ref container, string.Format(RustNET.msg("UI.Page", player.userID), page + 1, totalPages + 1), 11, "0.44 0.01", "0.56 0.04");
                RustNET.UI.Button(ref container, RustNET.uiColors[RustNET.Colors.Button], RustNET.msg("UI.Next", player.userID), 11, "0.56 0.01", "0.7 0.04", page + 1 <= totalPages ? $"rustnet.changepage {terminalId} {Title} {page + 1}" : "");
            }
            CuiHelper.DestroyUi(player, RustNET.RustNET_Panel);
            CuiHelper.AddUi(player, container);
        }
        [ConsoleCommand("securitycameras.control")]
        private void ccmdControl(ConsoleSystem.Arg arg) {
            BasePlayer player = arg.Connection.player as BasePlayer;
            if (player == null) return;
            if (!RustNET.linkManager.IsValidTerminal(arg.GetInt(1))) {
                CuiHelper.DestroyUi(player, RustNET.RustNET_Panel);
                SendReply(player, RustNET.msg("Warning.TerminalDestroyed", player.userID));
                return;
            }
            CuiHelper.DestroyUi(player, RustNET.RustNET_Panel);
            InitializeController(player, arg.GetUInt(0), arg.GetInt(1));
        }
#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("Help.Main", player.userID));
                SendReply(player, msg("Help.Add", player.userID));
                if (permission.UserHasPermission(player.UserIDString, permPublic)) SendReply(player, msg("Help.AddPublic", player.userID));
                SendReply(player, msg("Help.Remove", player.userID));
                SendReply(player, msg("Help.Name", player.userID));
                return;
            }
            if (configData.Camera.RequirePrivilege && !player.IsBuildingAuthed() &&!player.IsAdmin) {
                SendReply(player, msg("Error.NoPrivilege", player.userID));
                return;
            }
            switch (args[0].ToLower()) {
                case "add" : {
                    bool isPublic = permission.UserHasPermission(player.UserIDString, permPublic) && args.Length > 2 && args[1].ToLower() == "public";
                    Item activeItem = player.GetActiveItem();
                    if (activeItem == null || activeItem.info.itemid != CAMERA_ID) {
                        SendReply(player, msg("Error.NoCamera", player.userID));
                        return;
                    }
                    int cameraCount = 0;
                    BuildingManager.Building building = player.GetBuildingPrivilege()?.GetBuilding();
                    if (building != null) {
                        RustNET.LinkManager.Link buildingLink = RustNET.linkManager.GetLinkOf(building);
                        if (buildingLink == null && !isPublic) {
                            SendReply(player, msg("Error.NoTerminal", player.userID));
                            return;
                        }
                        cameraCount = linkManager.GetLinkOf(building)?.Managers.Count ?? 0;
                    }
                    else {
                        if (!isPublic) {
                            SendReply(player, msg("Error.NoBuildingPrivilege", player.userID));
                            return;
                        }
                    }
                    int cameraLimit = GetMaxCameras(player.userID);
                    if (!permission.UserHasPermission(player.UserIDString, permIgnore) && cameraCount >= cameraLimit) {
                        SendReply(player, msg("Error.Limit", player.userID));
                        return;
                    }
                    if (isPublic) {
                        int terminalId;
                        if (!int.TryParse(args[2], out terminalId)) {
                            SendReply(player, msg("Error.TerminalID", player.userID));
                            return;
                        }
                        if (!RustNET.linkManager.IsValidTerminal(terminalId)) {
                            SendReply(player, msg("Error.RustNETID", player.userID));
                            return;
                        }
                        RustNET.ItemPlacement placement = player.gameObject.AddComponent<RustNET.ItemPlacement>();
                        placement.terminalId = terminalId;
                        placement.SetRequiredItem(CAMERA_ID, new Vector3(0, 90, 0), new Vector3(0, 0, -0.1f), true, true, null, InitializeCamera, this);
                    }
                    else {
                        RustNET.ItemPlacement placement = player.gameObject.AddComponent<RustNET.ItemPlacement>();
                        placement.SetRequiredItem(CAMERA_ID, new Vector3(0, 90, 0), new Vector3(0, 0, -0.1f), true, false, InitializeCamera, null, this);
                    }
                    SendReply(player, msg("Placement.Enabled", player.userID));
                }
                return;
                case "remove" : {
                    CameraManager manager = RustNET.FindEntityFromRay(player)?.GetComponent<CameraManager>();
                    if (manager == null) {
                        SendReply(player, msg("Error.NoEntity", player.userID));
                        return;
                    }
                    if (manager.TerminalID != 0) {
                        RustNET.LinkManager.Link rustNetLink = RustNET.linkManager.GetLinkOf(manager.TerminalID);
                        if (rustNetLink != null && rustNetLink.IsPublicLink) {
                            if (!permission.UserHasPermission(player.UserIDString, permPublic)) {
                                SendReply(player, msg("Error.PublicLink", player.userID));
                                return;
                            }
                        }
                    }
                    LinkManager.CameraLink link = linkManager.GetLinkOf(manager);
                    if (link != null) link.OnCameraDestroyed(manager);
                    else UnityEngine.Object.Destroy(manager);
                    player.GiveItem(ItemManager.CreateByItemID(CAMERA_ID), BaseEntity.GiveItemReason.PickedUp);
                    SendReply(player, msg("Placement.Removed", player.userID));
                }
                return;
                case "name" : {
                    if (args.Length < 2) {
                        SendReply(player, msg("Error.NoNameSpecified", player.userID));
                        return;
                    }
                    CameraManager manager = RustNET.FindEntityFromRay(player)?.GetComponent<CameraManager>();
                    if (manager == null) {
                        SendReply(player, msg("Error.NoEntity", player.userID));
                        return;
                    }
                    manager.CameraName = args[1];
                    SendReply(player, string.Format(msg("Success.NameSet", player.userID), args[1]));
                }
                return;
                default : SendReply(player, msg("Error.InvalidCommand", player.userID));
                return;
            }
        }
#endregion
#region Image Management
        private void LoadDefaultImages(int attempts = 0) {
            if (attempts > 3) {
                PrintError("ImageLibrary not found.Unable to load camera overlay UI");
                configData.Camera.Overlay = false;
                return;
            }
            if (configData.Camera.Overlay && !string.IsNullOrEmpty(configData.Camera.OverlayImage)) AddImage("camoverlay", configData.Camera.OverlayImage);
            if (!string.IsNullOrEmpty(configData.Camera.RustNETIcon)) AddImage(Title, configData.Camera.RustNETIcon);
        }
        private void AddImage(string imageName, string fileName) => RustNET.ins.AddImage(imageName, fileName);
        private string GetImage(string name) => RustNET.ins.GetImage(name);
#endregion
#region Config
        private ConfigData configData;
        class ConfigData {
            [JsonProperty(PropertyName = "Camera Options")]
            public CameraOptions Camera {
                get;
                set;
            }
            public class CameraOptions {
                [JsonProperty(PropertyName = "Allow players to cycle through all linked cameras")]
                public bool CanCycle {
                    get;
                    set;
                }
                [JsonProperty(PropertyName = "Allow friends and clan members to place/remove cameras")]
                public bool Friends {
                    get;
                    set;
                }
                [JsonProperty(PropertyName = "Require building privilege to place/remove cameras")]
                public bool RequirePrivilege {
                    get;
                    set;
                }
                [JsonProperty(PropertyName = "Maximum allowed cameras per base (Permission | Amount)")]
                public Dictionary<string, int> Max {
                    get;
                    set;
                }
                [JsonProperty(PropertyName = "Camera placement and removal distance")]
                public int Distance {
                    get;
                    set;
                }
                [JsonProperty(PropertyName = "Display camera overlay UI")]
                public bool Overlay {
                    get;
                    set;
                }
                [JsonProperty(PropertyName = "Camera overlay image URL")]
                public string OverlayImage {
                    get;
                    set;
                }
                [JsonProperty(PropertyName = "Camera icon URL for RustNET menu")]
                public string RustNETIcon {
                    get;
                    set;
                }
            }
            public Oxide.Core.VersionNumber Version {
                get;
                set;
            }
        }
        protected override void LoadConfig() {
            base.LoadConfig();
            configData = Config.ReadObject<ConfigData>();
            if (configData.Version < Version) UpdateConfigValues();
            Config.WriteObject(configData, true);
        }
        protected override void LoadDefaultConfig() => configData = GetBaseConfig();
        private ConfigData GetBaseConfig() {
            return new ConfigData {
                Camera = new ConfigData.CameraOptions {
                    CanCycle = true, Distance = 4, Friends = true, Max = new Dictionary<string, int> {
                        ["securitycameras.use"]
                        = 4, ["securitycameras.pro"] = 10
                    }
                    , Overlay = true, OverlayImage = "http://www.rustedit.io/images/RustNET/camera.png", RustNETIcon = "http://www.rustedit.io/images/RustNET/cameraicon.png"
                }
                , Version = Version
            }
            ;
        }
        protected override void SaveConfig() => Config.WriteObject(configData, true);
        private void UpdateConfigValues() {
            PrintWarning("Config update detected! Updating config values...");
            ConfigData baseConfig = GetBaseConfig();
            if (configData.Version < new VersionNumber(0, 1, 05)) configData.Camera.Max = baseConfig.Camera.Max;
            if (configData.Version < new VersionNumber(0, 2, 0)) configData = baseConfig;
            if (configData.Version < new VersionNumber(0, 2, 10)) {
                configData.Camera.Overlay = baseConfig.Camera.Overlay;
                configData.Camera.OverlayImage = baseConfig.Camera.OverlayImage;
                configData.Camera.RustNETIcon = baseConfig.Camera.RustNETIcon;
            }
            if (configData.Version < new VersionNumber(0, 2, 14)) configData.Camera.CanCycle = baseConfig.Camera.CanCycle;
            configData.Version = Version;
            PrintWarning("Config update completed!");
        }
#endregion
#region Data Management
        private void SaveData() {
            storedData.cameraData = cameraManagers.Where(x => x != null).Select(x => x.GetCameraData()).ToArray();
            data.WriteObject(storedData);
        }
        private void LoadData() {
            try {
                storedData = data.ReadObject<StoredData>();
            }
            catch {
                storedData = new StoredData();
            }
        }
        private class StoredData {
            public CameraManager.CameraData[] cameraData = new CameraManager.CameraData[0];
        }
#endregion
#region Localization
        string msg(string key, ulong playerId = 0U) => lang.GetMessage(key, this, playerId == 0U ? null : playerId.ToString());
        Dictionary<string, string> Messages = new Dictionary<string, string> {
            ["Help.Main"]
            = "<color=#ce422b>/rustnet</color><color=#939393> - Display the help menu for using RustNET</color>", ["Help.Add"] = "<color=#ce422b>/sc add</color><color=#939393> - Activates the camera placement tool.Requires a camera in your hands!</color>", ["Help.AddPublic"] = "<color=#ce422b>/sc add public <terminal ID></color><color=#939393> - Activates the public camera placement tool.These cameras can be placed anywhere and need to be registered to a specific terminal</color>", ["Help.Remove"] = "<color=#ce422b>/sc remove</color><color=#939393> - Remove the camera you are looking at</color>", ["Help.Name"] = "<color=#ce422b>/sc name <name></color><color=#939393> - Set a name for the camera you are looking at</color>", ["Help.ControlInfo"] = "<color=#939393>Press <color=#ce422b>
// ... [Code preview truncated due to length. Full source in attached file] ...

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