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

FREE ZBillBoards : 1.3.0 1.3.0

Нет прав для скачивания
C#:
using UnityEngine;
using System.Collections.Generic;
using Oxide.Core;
using Newtonsoft.Json;
using System.Collections;
using UnityEngine.Networking;
using System.Drawing;
using System.IO;
using System.Drawing.Imaging;

namespace Oxide.Plugins
{
    [Info("ZBillBoards", "JOSH-Z", "1.3.0")]
    [Description("Create huge (or small) billboards")]
    public class ZBillBoards : RustPlugin
    {
        private static ZBillBoards ins;
        private GameObject downloadControllerObject;
        private DownloadController downloadController;
        private GameObject pasteControllerObject;
        private PasteController pasteController;

        const string permAdmin = "zbillboards.admin";
        const string permConsole = "zbillboards.console";
        const string permTier1 = "zbillboards.tier1";
        const string permTier2 = "zbillboards.tier2";
        const string permTier3 = "zbillboards.tier3";
        const string dataFileName = "ZBillBoards";

        #region Hooks
        void Init()
        {
            if (!LoadConfigVariables())
            {
                Puts("An error was found in your config file!");
                return;
            }

            permission.RegisterPermission(permAdmin, this);
            permission.RegisterPermission(permConsole, this);
            permission.RegisterPermission(permTier1, this);
            permission.RegisterPermission(permTier2, this);
            permission.RegisterPermission(permTier3, this);
        }

        void OnServerInitialized()
        {
            ins = this;

            downloadControllerObject = new GameObject("DownloadController");
            downloadController = downloadControllerObject.AddComponent<DownloadController>();

            pasteControllerObject = new GameObject("PasteController");
            pasteController = pasteControllerObject.AddComponent<PasteController>();

            ValidateAllBillboards();
        }

        void Unload()
        {
            SaveData();

            UnityEngine.Object.Destroy(downloadControllerObject);
            UnityEngine.Object.Destroy(pasteControllerObject);          
        }
        #endregion

        #region Download controller
        private static void ProcessImage(byte[] bytes, int targetWidth, int targetHeight, DownloadRequest request)
        {
            //byte[] bytesEditedImage;

            using (MemoryStream startBytes = new MemoryStream(), newBytes = new MemoryStream())
            {
                startBytes.Write(bytes, 0, bytes.Length);

                Bitmap image = new Bitmap(startBytes);
                Bitmap finalImage = new Bitmap(targetWidth, targetHeight);

                using (System.Drawing.Graphics graphics = System.Drawing.Graphics.FromImage(finalImage))
                {
                    graphics.DrawImage(image, new Rectangle(0, 0, targetWidth, targetHeight));
                }


                // worry about this later, very heavy because pixel per pixel
                //if (request.adjustBrightness)
                //{                    
                //    bytesEditedImage = RecolorImage(newBytes, targetWidth, targetHeight);
                //    newBytes.Write(bytesEditedImage, 0, bytesEditedImage.Length);
                //}

                finalImage.Save(newBytes, ImageFormat.Png);

                SplitImageAndPaste(request, finalImage, ins.configData.imageSize, ins.configData.imageSize);

                image.Dispose();
                finalImage.Dispose();
            }
        }

        //private static void ProcessDrawing(Signage sign, int targetWidth, int targetHeight, DownloadRequest request)
        //{
        //    //byte[] bytesEditedImage;

        //    var textureId = sign.textureIDs[0];
        //    if (textureId == 0)
        //    {
        //        Debug.LogError("Image texture ID is 0");
        //        return;
        //    }

        //    var imageByte = FileStorage.server.Get(textureId, FileStorage.Type.png, sign.net.ID);
        //    using (MemoryStream ms = new MemoryStream(imageByte))
        //    {
        //        Bitmap image = (Bitmap)Image.FromStream(ms);


        //        Bitmap finalImage = new Bitmap(targetWidth, targetHeight);

        //        using (System.Drawing.Graphics graphics = System.Drawing.Graphics.FromImage(finalImage))
        //        {
        //            graphics.DrawImage(image, new Rectangle(0, 0, targetWidth, targetHeight));

        //        }
        //            SplitImageAndPaste(request, image, ins.configData.imageSize, ins.configData.imageSize);

               

        //        image.Dispose();
        //    }
        //}

        private static void SplitImageAndPaste(DownloadRequest request, Bitmap sourceImage, int defWidth, int defHeight)
        {
            if(ins.configData.debug)
                Debug.Log("Image url: " + request.imageURL);

            if (request.targetSign == null)
            {
                ins.pasteController.PasteNextFromList();
                return;
            }

            BillBoardData billBoardData;
            if (!ins.storedData.billBoards.TryGetValue(request.targetSign.net.ID, out billBoardData)) return;

            var sTotCols = request.width;
            var curCol = 1;
            var curRow = 1;

            foreach (uint signID in billBoardData.billBoardSigns)
            {
                byte[] imagePart = GetImagePart(sourceImage, ins.configData.imageSize, ins.configData.imageSize, curCol, curRow);
                ins.pasteController.AddToPasteList(imagePart, signID, curCol, curRow);

                if (curCol == sTotCols)
                {
                    curCol = 1;
                    curRow++;
                }
                else
                {
                    curCol++;
                }
            }

            sourceImage.Dispose();

            ins.pasteController.PasteNextFromList();
        }

        private static byte[] RecolorImage(MemoryStream stream, int targetWidth, int targetHeight)
        {
            var bytes = stream.ToArray();

            float b = ins.configData.brightness;
            ColorMatrix cm = new ColorMatrix(new float[][]
            {
                new float[] {b, 0, 0, 0, 0},
                new float[] {0, b, 0, 0, 0},
                new float[] {0, 0, b, 0, 0},
                new float[] {0, 0, 0, 1, 0},
                new float[] {0, 0, 0, 0, 1},
            });
            ImageAttributes attributes = new ImageAttributes();
            attributes.SetColorMatrix(cm);

            using (MemoryStream originalBytesStream = new MemoryStream())
            {
                originalBytesStream.Write(bytes, 0, bytes.Length);
                Bitmap sourceImage = new Bitmap(originalBytesStream);
                Bitmap targetImage = new Bitmap(targetWidth, targetHeight);


                Point[] targetRectPoints = { new Point(0, 0), new Point(targetWidth, 0), new Point(0, targetHeight) };
                using (System.Drawing.Graphics graphics = System.Drawing.Graphics.FromImage(targetImage))
                {
                    var sourceRectangle = new Rectangle(0, 0, targetWidth, targetHeight);
                    graphics.DrawImage(sourceImage, targetRectPoints, sourceRectangle, GraphicsUnit.Pixel, attributes);
                }

                var recoloredImageBytes = originalBytesStream.ToArray();
                //targetImage.Dispose();
                //sourceImage.Dispose();

                return recoloredImageBytes;
            }           
        }

        private class DownloadController : FacepunchBehaviour
        {            
            private byte downloading;
            private readonly Queue<DownloadRequest> downloadQueue = new Queue<DownloadRequest>();

            public void QueueDownload(string url, BasePlayer player, Signage sign, int width, int height, bool adjustBrightness)
            {
                downloadQueue.Enqueue(new DownloadRequest(url, player, sign, width, height, adjustBrightness));
                StartNewDownload();
            }

            private byte[] GetDownloadResponse(UnityWebRequest webRequest)
            {
                Texture2D texture = new Texture2D(2, 2);
                texture.LoadImage(webRequest.downloadHandler.data);

                byte[] image;
                image = texture.EncodeToPNG();

                DestroyImmediate(texture);
                return image;
            }

            private void StartNewDownload()
            {
                if (downloading >= 1) return;                
                if (downloadQueue.Count <= 0)
                {
                    if(ins.configData.debug)
                        Debug.Log("Billboard download queue empty, stopped Coroutine");
                    return;
                }
                downloading++;
                StartCoroutine(StartDownload(downloadQueue.Dequeue()));
            }

            private IEnumerator StartDownload(DownloadRequest request)
            {
                Debug.Log("Billboard image download started for " + request.player.displayName + " - Image url: " + request.imageURL);

                UnityWebRequest webRequest = UnityWebRequest.Get(request.imageURL);
                yield return webRequest.SendWebRequest();

                if (webRequest.isNetworkError || webRequest.isHttpError)
                {
                    Debug.Log("Billboard image download failed for image url: " + request.imageURL + " - Error: " + (webRequest.error != null ? webRequest.error : "N/A"));
                    if(request.player != null && request.player.IsConnected)
                        request.player.ChatMessage("Failed to download your image, error: " + (webRequest.error != null ? webRequest.error : "Unknown"));

                    webRequest.Dispose();

                    downloading--;
                    StartNewDownload();
                    yield break;
                }

                byte[] downloadResponse;
                downloadResponse = GetDownloadResponse(webRequest);

                int defWidth = ins.configData.imageSize * request.width;
                int defHeight = ins.configData.imageSize * request.height;

                ProcessImage(downloadResponse, defWidth, defHeight, request);

                //if(request.adjustBrightness)
                //    resizedImageBytes = RecolorImage(downloadResponse, defWidth, defHeight);


                downloading--;

                StartNewDownload();
                webRequest.Dispose();

            }                   
        }

        private class DownloadRequest
        {
            public BasePlayer player { get; }
            public Signage targetSign { get; }
            public string imageURL { get; set; }
            public int width { get; set; } = 1;
            public int height { get; set; } = 1;
            public bool adjustBrightness { get; set; }

            public DownloadRequest(string url, BasePlayer inputPlayer, Signage inputSign, int inputWidth, int inputHeight, bool inpBrightness)
            {
                imageURL = url;
                player = inputPlayer;
                targetSign = inputSign;
                width = inputWidth;
                height = inputHeight;
                adjustBrightness = inpBrightness;
            }
        }
        #endregion

        #region Paste Controller
        private class PasteController : FacepunchBehaviour
        {
            private bool isPasting = false;
            private List<PasteRequest> pasteList = new List<PasteRequest>();

            public void AddToPasteList(byte[] imgData, uint signID, int coordsX, int coordsY)
            {
                pasteList.Add(new PasteRequest(imgData, signID, coordsX, coordsY));
            }

            public void PasteNextFromList()
            {
                if (isPasting) return;
                if (pasteList.Count == 0) return;

                isPasting = true;

                var request = pasteList[0];
                pasteList.RemoveAt(0);

                PasteImage(request);
            }

            public void ClearPasteList()
            {
                isPasting = true;
                pasteList.Clear();
                isPasting = false;
            }

            public int GetEmptyFrame(Signage sign)
            {
                for (int index = 0; index < sign.textureIDs.Length; index++)
                {
                    if (sign.textureIDs[index] == 0)
                        return index;
                }
                return 0;
            }

            private void PasteImage(PasteRequest request)
            {
                Signage targetSign = BaseNetworkable.serverEntities.Find(request.signID) as Signage;
                if (targetSign == null)
                {
                    isPasting = false;
                    return;
                }

                targetSign.EnsureInitialized();

                var frameNumber = GetEmptyFrame(targetSign);
                var currentTextureID = targetSign.textureIDs[frameNumber];

                if (currentTextureID != 0)
                    FileStorage.server.RemoveExact(currentTextureID, FileStorage.Type.png, targetSign.net.ID, (uint)frameNumber);

                var textureId = FileStorage.server.Store(request.imgData, FileStorage.Type.png, targetSign.net.ID, (uint)frameNumber);
                targetSign.textureIDs[frameNumber] = textureId;
                targetSign.SendNetworkUpdate();

                if(ins.configData.debug)
                    Debug.Log("Pasted image on sign " + targetSign.net.ID + ", " + ins.pasteController.pasteList.Count + " signs left");


                isPasting = false;

                Invoke("PasteNextFromList", ins.configData.pasteDelay);
            }
        }

        private class PasteRequest
        {
            public uint signID { get; }
            public byte[] imgData { get; }
            public int signX { get; }
            public int signY { get; }

            public PasteRequest(byte[] inpImgData, uint inpSignID, int coordsX, int coordsY)
            {
                imgData = inpImgData;
                signID = inpSignID;
                signX = coordsX;
                signY = coordsY;
            }
        }

        private static byte[] GetImagePart(Bitmap sourceImage, int targetWidth, int targetHeight, int splitX, int splitY)
        {
            byte[] bytesClipped;

            var streamResized = new MemoryStream();
            Bitmap targetImage = new Bitmap(targetWidth, targetHeight);

            int pixelsX = (splitX - 1) * targetWidth;
            int pixelsY = (splitY - 1) * targetHeight;
            Point[] targetRectPoints = { new Point(0, 0), new Point(targetWidth, 0), new Point(0, targetHeight) };

            using (System.Drawing.Graphics graphics = System.Drawing.Graphics.FromImage(targetImage))
            {
                var sourceRectangle = new Rectangle(pixelsX, pixelsY, targetWidth, targetHeight);
                graphics.DrawImage(sourceImage, targetRectPoints, sourceRectangle, GraphicsUnit.Pixel);
            }

            AddRandomPixel(targetImage);

            targetImage.Save(streamResized, ImageFormat.Png);
            bytesClipped = streamResized.ToArray();
            targetImage.Dispose();

            return bytesClipped;
        }

        #endregion

        #region Commands
        [ConsoleCommand("billboard.toggle")]
        private void consoleCmdZDP(ConsoleSystem.Arg arg)
        {
            var player = arg.Player();
            if (player == null)
                return;

            if (!HasPermission(player.UserIDString, permConsole))
                return;

            if (arg.Args.Length > 0)
            {
                uint posID;
                if (!uint.TryParse(arg.Args[0], out posID)) return;

                NeonSign mainSign = GetMainSign(posID) as NeonSign;
                if (mainSign == null) return;

                if (configData.debug)
                    Puts("Console command used to toggle power on billboard " + posID);

                SwitchBillBoardPower(mainSign);
            }
        }

        [ChatCommand("billboard")]
        private void cmdBillBoard(BasePlayer player, string command, string[] args)
        {
            var maxSigns = 0;
            var maxBillboards = 0;
            if(HasPermission(player.UserIDString, permAdmin)) {
                maxSigns = configData.maxSignsAdmin;
                maxBillboards = configData.maxBillboardsAdmin;
            }
            else if (HasPermission(player.UserIDString, permTier3)) {
                maxSigns = configData.maxSignsTier3;
                maxBillboards = configData.maxBillboardsTier3;
            }
            else if (HasPermission(player.UserIDString, permTier2)) {
                maxSigns = configData.maxSignsTier2;
                maxBillboards = configData.maxBillboardsTier2;
            }
            else if (HasPermission(player.UserIDString, permTier1)) {
                maxSigns = configData.maxSignsTier1;
                maxBillboards = configData.maxBillboardsTier1;
            }
            else
            {
                player.ChatMessage("No permission");
                return;
            }

            if (args.Length > 0)
            {
                switch (args[0])
                {
                    case "create": CreateBillBoard(player, args, maxSigns, maxBillboards); break;
                    case "remove":
                    case "destroy": DestroyBillBoard(player); break;
                    case "destroyall": DestroyBillBoards(player); break;
                    case "info": ShowBillboardInfo(player); break;
                    case "debug": ToggleDebug(player); break;
                    case "addsign": AddSignToBillboard(player, args); break;
                    case "toggle": ToggleBillBoardPower(player); break;
                    case "speed": ChangeBillBoardSpeed(player, args); break;
                    case "dimmer": ChangeBillBoardDimmer(player, args); break;
                    case "next": CommandPasteNext(player); break;
                    case "emptypaste": CommandPasteEmpty(player); break;
                    case "sil": SilBillBoard(player, args); break;
                    //case "draw": DrawingToBillBoard(player, args); break;
                }
            }
        }
        #endregion

        #region Functions
        // for next version
        //public void DrawingToBillBoard(BasePlayer player, string[] args)
        //{
        //    if (!selectedSigns.ContainsKey(player))
        //        selectedSigns.Add(player, null);

        //    if(args.Length == 3)
        //    {
        //        int cols;
        //        int rows;
        //        if (!int.TryParse(args[1], out cols) || !int.TryParse(args[2], out rows))
        //        {
        //            player.ChatMessage("Incorrect syntax: /billboard draw 3 2");
        //            return;
        //        }

        //        var startSign = GetBillBoard(player);
        //        if (startSign == null) return;

        //        Signage selectedSign;
        //        if (!selectedSigns.TryGetValue(player, out selectedSign) || selectedSign == null)
        //        {
        //            player.ChatMessage("Select a source sign first: /billboard draw select");
        //            return;
        //        }

        //        player.ChatMessage("Drawing painting from sign to billboard");
        //        ProcessDrawing(selectedSign, cols, rows, new DownloadRequest("", player, startSign, cols, rows, false));
        //    }
        //    else if(args.Length > 1)
        //    {
        //        switch(args[1])
        //        {
        //            case "select":
        //                RaycastHit hit;
        //                if (!Physics.Raycast(player.eyes.HeadRay(), out hit, 6f))
        //                {
        //                    player.ChatMessage("Please look at a sign!");
        //                    return;
        //                }

        //                var sourceSign = hit.GetEntity() as Signage;
        //                if(sourceSign == null)
        //                {
        //                    player.ChatMessage("Please look at a sign!");
        //                    return;
        //                }

        //                selectedSigns[player] = sourceSign;
        //                player.ChatMessage("Selected " + sourceSign.ShortPrefabName);
        //                break;
        //        }
        //    }
        //    else
        //    {
        //        player.ChatMessage("Incorrect syntax: /billboard draw select | /billboard draw 3 2");
        //        return;
        //    }
        //}

        public void ValidateAllBillboards()
        {
            var allBB = new Dictionary<uint, BillBoardData>(storedData.billBoards);
            Puts("Validating " + allBB.Count + " billboards...");
            foreach(var mainSign  in allBB)
            {
                ValidateBillboard(mainSign.Key);               
            }

            Puts("All billboards validated");
        }

        public void ValidateBillboard(uint mainSignID)
        {
            BillBoardData billBoardData;
            if(!storedData.billBoards.TryGetValue(mainSignID, out billBoardData))
            {
                Puts("Trying to validate a non-existing billboard");
                return;
            }

            Signage signage = BaseNetworkable.serverEntities.Find(mainSignID) as Signage;
            if (signage == null)
            {
                storedData.billBoards.Remove(mainSignID);

                RemoveFromUserBillboards(mainSignID);

                Puts("Deleted billboard " + mainSignID + " as it does not exist anymore");
                return;
            }

            var speed = 3f;
            if (billBoardData.speed > 0)
                speed = billBoardData.speed;

            Puts("Billboard " + mainSignID + " has " + billBoardData.billBoardSigns.Count + " signs, validating...");
            foreach (var subSign in billBoardData.billBoardSigns)
            {
                Signage subSignage = BaseNetworkable.serverEntities.Find(subSign) as Signage;
                if (subSignage == null)
                {
                    storedData.billBoards[mainSignID].billBoardSigns.Remove(subSign);
                    Puts("Deleted sign " + subSign + " from billboard " + mainSignID);
                    continue;
                }

                var subSignNeon = subSignage as NeonSign;
                if (subSignNeon != null)
                {
                    subSignNeon.animationSpeed = speed;
                    subSignNeon.UpdateHasPower(0, 0);
                }
            }

            if (signage is NeonSign)
                SwitchBillBoardPower(signage as NeonSign, 25);

            Puts("Billboard validated");
        }

        public void ToggleBillBoardPower(BasePlayer player)
        {
            var billboardSign = GetBillBoard(player) as NeonSign;
            if (billboardSign == null) return;

            SwitchBillBoardPower(billboardSign);

            player.ChatMessage("Billboard power toggled");
            return;
        }

        public void AddSignToBillboard(BasePlayer player, string[] args)
        {
            if (args.Length == 0) return;

            var newSign = GetBillBoard(player, false);
            if (newSign == null) return;

           

            uint inpID;
            if (!uint.TryParse(args[1], out inpID))
            {
                player.ChatMessage("Invalid billboard ID");
                return;
            }


            if (!storedData.billBoards.ContainsKey(inpID))
            {
                player.ChatMessage("Billboard not found");
                return;
            }

            if (storedData.billBoards[inpID].billBoardSigns.Contains(newSign.net.ID))
            {
                player.ChatMessage("Already in billboard!");
                return;
            }

            storedData.billBoards[inpID].billBoardSigns.Add(newSign.net.ID);

            newSign.UpdateHasPower(25, 0);
            newSign.SendNetworkUpdate();

            player.ChatMessage("Sign added to billboard");
            return;
        }

        public void ToggleDebug(BasePlayer player = null)
        {
            configData.debug = !configData.debug;
            SaveConf();

            player.ChatMessage("Debug mode set to: " + configData.debug);
            return;
        }

        private void SwitchBillBoardPower(NeonSign billboardSign, int forcePower = -1)
        {
            int newPower = billboardSign.IsPowered() ? 0 : 25;
            if (forcePower >= 0)
                newPower = forcePower;

            BillBoardData billBoardData;
            if (!ins.storedData.billBoards.TryGetValue(billboardSign.net.ID, out billBoardData)) return;

            foreach (uint signID in billBoardData.billBoardSigns)
            {
                Signage signage = BaseNetworkable.serverEntities.Find(signID) as Signage;
                if (signage == null) continue;

                Interface.CallHook("OnBillboardPowerToggled", billboardSign.net.ID, signage, newPower > 0);

                signage.UpdateHasPower(newPower, 0);
                signage.SendNetworkUpdate();
            }
        }

        public void ChangeBillBoardSpeed(BasePlayer player, string[] args)
        {
            var billboardSign = GetBillBoard(player) as NeonSign;
            if (billboardSign == null) return;

            if (args.Length != 2)
            {
                player.ChatMessage("Wrong usage: /billboard speed 3");
                return;
            }

            BillBoardData billBoardData;
            if (!storedData.billBoards.TryGetValue(billboardSign.net.ID, out billBoardData))
            {
                player.ChatMessage("Billboard not found");
                return;
            }

            float newSpeed;
            if (!float.TryParse(args[1], out newSpeed) && newSpeed >= 0) {
                player.ChatMessage("Invalid speed, usage: /billboard speed 3");
                return;
            }            

            billBoardData.speed = newSpeed;

            foreach (uint signID in billBoardData.billBoardSigns)
            {
                NeonSign signage = BaseNetworkable.serverEntities.Find(signID) as NeonSign;
                if (signage == null) continue;

                signage.animationSpeed = newSpeed;
                signage.SendNetworkUpdate();
            }

            SwitchBillBoardPower(billboardSign);
            SwitchBillBoardPower(billboardSign);

            player.ChatMessage("Billboard speed set to: "+ newSpeed);
            return;
        }

        public void ChangeBillBoardDimmer(BasePlayer player, string[] args)
        {
            var billboardSign = GetBillBoard(player);
            if (billboardSign == null) return;

            if (args.Length != 2)
            {
                player.ChatMessage("Wrong usage: /billboard dimmer 2");
                return;
            }

            float newIntensity = 2f;
            float intensity = 1f;
            if (float.TryParse(args[1], out intensity) && intensity >= 0) newIntensity = intensity;

            BillBoardData billBoardData;
            if (!ins.storedData.billBoards.TryGetValue(billboardSign.net.ID, out billBoardData)) return;

            foreach (uint signID in billBoardData.billBoardSigns)
            {
                NeonSign signage = BaseNetworkable.serverEntities.Find(signID) as NeonSign;
                if (signage == null) return;

                signage.lightIntensity = newIntensity;
                signage.SendNetworkUpdate();
            }

            player.ChatMessage("Billboard dimmer set to: " + newIntensity);
            return;
        }

        public void SilBillBoard(BasePlayer player, string[] args)
        {
            if (args.Length < 2)
            {
                //player.ChatMessage("Incorrect syntax: /billboard sil <url> [darker]");
                player.ChatMessage("Incorrect syntax: /billboard sil <url>");
                return;
            }

            var startSign = GetBillBoard(player);
            if (startSign == null) return;

            BillBoardData billBoardData;
            if(!storedData.billBoards.TryGetValue(startSign.net.ID, out billBoardData))
            {
                player.ChatMessage("This sign does not seem te be part of a billboard");
                return;
            }

            bool adjustBrightness = false;
            if (args.Length > 2 && args[2] == "true")
                adjustBrightness = true;

            downloadController.QueueDownload(args[1], player, startSign, billBoardData.signsHorizontal, billBoardData.signsVertical, adjustBrightness);
            player.ChatMessage("Loading images...");           
        }

        public void DestroyBillBoards(BasePlayer player)
        {
            if (!HasPermission(player.UserIDString, permAdmin))
                return;            

            foreach (var billBoardData in storedData.billBoards)
            {
                foreach (uint signID in billBoardData.Value.billBoardSigns)
                {
                    BaseEntity ent = BaseNetworkable.serverEntities.Find(signID) as BaseEntity;
                    if (ent != null)
                    {
                        ent.Kill();
                    }
                }
            }
            storedData.billBoards.Clear();
            storedData.userBillboards.Clear();
        }

        public void DestroyBillBoard(BasePlayer player)
        {
            var sign = GetBillBoard(player);
            if (sign == null) return;

            uint sid = sign.net.ID;
            BillBoardData billBoardData;
            if (!ins.storedData.billBoards.TryGetValue(sid, out billBoardData)) return;

            var signItemName = sign is NeonSign ? "sign.neon.xl.animated" : "sign.pictureframe.xl";


            foreach (uint signID in billBoardData.billBoardSigns)
            {
                BaseEntity ent = BaseNetworkable.serverEntities.Find(signID) as BaseEntity;
                if (ent != null) ent.Kill();                
            }
            storedData.billBoards.Remove(sid);

            RemoveFromUserBillboards(sid);

            if(configData.refundOnDestroy)
            {
                var item = ItemManager.CreateByName(signItemName);
                if(item != null)
                    player.GiveItem(item);
            }

            player.ChatMessage("Billboard destroyed");
        }

        public void RemoveFromUserBillboards(uint sid)
        {
            var userBBs = new Dictionary<string, List<uint>>(storedData.userBillboards);
            foreach (var ubb in userBBs)
            {
                if (!ubb.Value.Contains(sid)) continue;

                storedData.userBillboards[ubb.Key].Remove(sid);

                if (storedData.userBillboards[ubb.Key].Count == 0)
                    storedData.userBillboards.Remove(ubb.Key);
            }
        }

        public Signage GetBillBoard(BasePlayer player, bool checkIfBillBoard = true)
        {
            RaycastHit hit;
            if (!Physics.Raycast(player.eyes.HeadRay(), out hit, 6f))
            {
                player.ChatMessage("Please look at a billboard!");
                return null;
            }

            Signage billboardSign = null;
            billboardSign = hit.GetEntity() as Signage;

            
            if (billboardSign == null || (!billboardSign.ShortPrefabName.Contains("sign.neon.xl.animated") && !billboardSign.ShortPrefabName.Contains("sign.pictureframe.xl")))
            {
                player.ChatMessage("Cannot find Billboard / XL Animated Neon sign / XL Pictureframe!");
                return null;
            }

            if(!checkIfBillBoard)
            {
                return billboardSign;
            }

            Signage mainSign = GetMainSign(billboardSign.net.ID);
            if (checkIfBillBoard && mainSign == null)
            {
                player.ChatMessage("Please look at a billboard!");
                return null;
            }
           
            return mainSign;            
        }

        public Signage GetMainSign(uint raySignID)
        {
            uint parentSignID = 0;

            foreach (var billBoardData in storedData.billBoards)
            {
                foreach (uint subSignID in billBoardData.Value.billBoardSigns)
                {
                    if(subSignID == raySignID)
                    {
                        parentSignID = billBoardData.Key;
                        break;
                    }                    
                }

                if (parentSignID != 0) break;
            }

            if (parentSignID == 0)
                return null;

            Signage ent = BaseNetworkable.serverEntities.Find(parentSignID) as Signage;
            if (ent == null)
                return null;

            return ent;        
        }

        public void ShowBillboardInfo(BasePlayer player)
        {
            var billboard = GetBillBoard(player);
            if(billboard != null)
                player.ChatMessage("Billboard ID: " + billboard.net.ID + "\nLocation: " + billboard.transform.position);
        }

        public void CreateBillBoard(BasePlayer player, string[] args, int maxSigns, int maxBillboards)
        {
            int horizontal = 3;
            int vertical = 2;

            List<uint> userBillboards;
            if(maxBillboards > 0 && storedData.userBillboards.TryGetValue(player.UserIDString, out userBillboards) && userBillboards.Count >= maxBillboards)
            {
                player.ChatMessage("Failed creating billboard: You have reached the limit (" + maxBillboards + ")");
                return;
            }

            if (args.Length == 3)
            {
                int inputH;
                int inputV;
                if (int.TryParse(args[1], out inputH) && int.TryParse(args[2], out inputV) && inputH > 0 && inputV > 0 && (inputH * inputV) < maxSigns)
                {
                    horizontal = inputH;
                    vertical = inputV;
                }
            }

            if(!HasPermission(player.UserIDString, permAdmin) && player.IsBuildingBlocked())
            {
                player.ChatMessage("You can not create billboards in building blocked zones");
                return;
            }

            if(horizontal * vertical > maxSigns)
            {
                player.ChatMessage("The total of signs can not be higher than " + maxSigns);
                return;
            }

            var startSign = GetBillBoard(player, false);
            if (startSign == null)
            {
                player.ChatMessage("Can not find the main billboard sign");
                return;
            }

            if (storedData.billBoards.ContainsKey(startSign.net.ID))
            {
                player.ChatMessage("This is already a billboard");
                return;
            }

            storedData.billBoards.Add(startSign.net.ID, new BillBoardData());

            BillBoardData billBoardData;
            if (!storedData.billBoards.TryGetValue(startSign.net.ID, out billBoardData))
            {
                player.ChatMessage("Something went wrong while creating the billboard");
                return;
            }

            billBoardData.billBoardSigns.Add(startSign.net.ID);
            billBoardData.signsHorizontal = horizontal;
            billBoardData.signsVertical = vertical;

            if (!storedData.userBillboards.ContainsKey(player.UserIDString))
                storedData.userBillboards.Add(player.UserIDString, new List<uint>());
            storedData.userBillboards[player.UserIDString].Add(startSign.net.ID);

            if (configData.lockSigns)
                startSign.SetFlag(BaseEntity.Flags.Locked, true, false, true);

            string prefab = "assets/prefabs/misc/xmas/neon_sign/sign.neon.xl.animated.prefab";
            float offset = -2.5f;
            var rotation = startSign.transform.rotation;

            var startSignNeon = startSign as NeonSign;
            if (startSignNeon != null)
            {
                startSignNeon.UpdateHasPower(25, 0);
                startSignNeon.SendNetworkUpdate();                
            }
            else
            {
                prefab = "assets/prefabs/deployable/signs/sign.pictureframe.xl.prefab";
                offset = -2.7f;
            }

            

            for (int col = 0; col < vertical; col++)
            {
                for (int row = 0; row < horizontal; row++)
                {
                    if (row == 0 && col == 0) continue;

                    var newPosition = startSign.transform.position + (startSign.transform.right * row * offset) + (startSign.transform.up * col * offset);

                    Signage sign = GameManager.server.CreateEntity(prefab, newPosition, rotation) as Signage;
                    if (sign == null) return;
                    sign.Spawn();
                    sign.OwnerID = player.userID;

                    if (configData.lockSigns)
                        sign.SetFlag(BaseEntity.Flags.Locked, true, false, true);

                    if (sign is NeonSign)
                    {
                        sign.UpdateHasPower(25, 0);
                        sign.SendNetworkUpdate();
                    }

                    //storedData.billBoards[startSign.net.ID].billBoardSigns.Add(sign.net.ID);
                    billBoardData.billBoardSigns.Add(sign.net.ID);
                    
                    if(configData.debug)
                        Puts("Billboard part " + row + " x " + col + " spawned at " + newPosition);
                }
            }
        }
        
        public void CommandPasteNext(BasePlayer player)
        {
            if (!HasPermission(player.UserIDString, permAdmin))
                return;

            if (pasteController != null)
            {
                pasteController.PasteNextFromList();
                player.ChatMessage("Pasting next frame...");
                return;
            }
        }

        public void CommandPasteEmpty(BasePlayer player)
        {
            if (!HasPermission(player.UserIDString, permAdmin))
                return;

            if (pasteController != null)
            {
                pasteController.ClearPasteList();
                player.ChatMessage("PasteList cleared...");
                return;
            }
        }
        #endregion

        #region Helpers
        public UnityEngine.Random rnd = new UnityEngine.Random();
        private static void AddRandomPixel(Bitmap image)
        {
            var color = System.Drawing.Color.FromArgb(
                UnityEngine.Random.Range(0, 255),
                UnityEngine.Random.Range(0, 255),
                UnityEngine.Random.Range(0, 255),
                128 //Alpha (transparency)
            );
            image.SetPixel(image.Width - 1, 1, color);
        }

        bool HasPermission(string id, string perm) => permission.UserHasPermission(id, perm);

        #endregion

        #region Config
        private ConfigData configData;

        class ConfigData
        {
            [JsonProperty(PropertyName = "Maximum amount of signs in total (width x height) Tier 1")]
            public int maxSignsTier1 = 6;

            [JsonProperty(PropertyName = "Maximum amount of billboards (any size, 0 = unlimited) Tier 1")]
            public int maxBillboardsTier1 = 1;

            [JsonProperty(PropertyName = "Maximum amount of signs in total (width x height) Tier 2")]
            public int maxSignsTier2 = 12;

            [JsonProperty(PropertyName = "Maximum amount of billboards (any size, 0 = unlimited) Tier 2")]
            public int maxBillboardsTier2 = 3;

            [JsonProperty(PropertyName = "Maximum amount of signs in total (width x height) Tier 3")]
            public int maxSignsTier3 = 16;

            [JsonProperty(PropertyName = "Maximum amount of billboards (any size, 0 = unlimited) Tier 3")]
            public int maxBillboardsTier3 = 5;

            [JsonProperty(PropertyName = "Maximum amount of signs in total (width x height) Admin")]
            public int maxSignsAdmin = 150;

            [JsonProperty(PropertyName = "Maximum amount of billboards (any size, 0 = unlimited) Admin")]
            public int maxBillboardsAdmin = 0;

            [JsonProperty(PropertyName = "Width and height of each neon sign image in pixels")]
            public int imageSize = 150;

            [JsonProperty(PropertyName = "Seconds between pasting images")]
            public float pasteDelay = 0.5f;

            [JsonProperty(PropertyName = "Brightness of the images pasted on the billboards (experimental)")]
            public float brightness = 0.5f;

            [JsonProperty(PropertyName = "Lock signs to owner after creating billboard")]
            public bool lockSigns = false;

            [JsonProperty(PropertyName = "Give back a Neon Sign when a billboard is removed with the destroy command")]
            public bool refundOnDestroy = true;

            [JsonProperty(PropertyName = "Log extra output to console")]
            public bool debug = false;
        }

        private bool LoadConfigVariables()
        {
            try
            {
                configData = Config.ReadObject<ConfigData>();
            }
            catch
            {
                return false;
            }
            SaveConf();
            return true;
        }

        protected override void LoadDefaultConfig()
        {
            Puts("Creating new config file.");
            configData = new ConfigData();
            SaveConf();
        }

        void SaveConf() => Config.WriteObject(configData, true);
        #endregion

        #region Data
        StoredData storedData;
        class StoredData
        {
            public Dictionary<uint, BillBoardData> billBoards = new Dictionary<uint, BillBoardData>();
            public Dictionary<string, List<uint>> userBillboards = new Dictionary<string, List<uint>>();
        }

        class BillBoardData
        {
            public float speed = 3f;
            public int signsHorizontal = 0;
            public int signsVertical = 0;
            public List<uint> billBoardSigns = new List<uint>();
            
        }

        void Loaded()
        {
            LoadData();
        }

        public void LoadData()
        {
            try
            {
                storedData = Interface.Oxide.DataFileSystem.ReadObject<StoredData>(dataFileName);
            }
            catch
            {
                storedData = new StoredData();
                Puts("Invalid datafile, new file generated");

                SaveData();
            }

            if (storedData == null)
            {
                storedData = new StoredData();
                Puts("Invalid datafile, new file generated");

                SaveData();
            }
        }

        void SaveData()
        {
            Interface.Oxide.DataFileSystem.WriteObject(dataFileName, storedData);
        }
        #endregion
    }
}

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

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

Сверху