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

FREE SignArtist : 1.2.62 1.2.62

Нет прав для скачивания
C#:
// Reference: System.Drawing
using Newtonsoft.Json;
using Oxide.Core;
using Oxide.Plugins.SignArtistClasses;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using Oxide.Core.Libraries.Covalence;
using UnityEngine;
using UnityEngine.Networking;
using Color = System.Drawing.Color;
using Graphics = System.Drawing.Graphics;
using Steamworks;
namespace Oxide.Plugins {
    [Info("Sign Artist", "Whispers88", "1.2.62")]
    [Description("Allows players with the appropriate permission to import images from the internet on paintable objects")]
    /*********************************************************************************
     * This plugin was originally created by Bombardir and then maintained by Nogrod.* It was rewritten from scratch by Mughisi on January 12th, 2018.*********************************************************************************/
    internal class SignArtist : RustPlugin {
        private Dictionary<ulong, float> cooldowns = new Dictionary<ulong, float>();
        private GameObject imageDownloaderGameObject;
        private ImageDownloader imageDownloader;
        SignArtistConfig Settings {
            get;
            set;
        }
        Dictionary<string, ImageSize> ImageSizePerAsset {
            get;
            set;
        }
        Dictionary<ulong, string> SkiniconUrls = new Dictionary<ulong, string>();
        private const string ItemIconUrl = "https://www.rustedit.io/images/imagelibrary/{0}.png";
        /// <summary>
        /// Plugin configuration
        /// </summary>
        public class SignArtistConfig {
            [JsonProperty(PropertyName = "Time in seconds between download requests (0 to disable)")]
            public int Cooldown {
                get;
                set;
            }
            [JsonProperty(PropertyName = "Maximum concurrent downloads")]
            public int MaxActiveDownloads {
                get;
                set;
            }
            [JsonProperty(PropertyName = "Maximum distance from the sign")]
            public int MaxDistance {
                get;
                set;
            }
            [JsonProperty(PropertyName = "Maximum filesize in MB")]
            public float MaxSize {
                get;
                set;
            }
            [JsonProperty(PropertyName = "Enforce JPG file format")]
            public bool EnforceJpeg {
                get;
                set;
            }
            [JsonProperty(PropertyName = "JPG image quality (0-100)")]
            public int Quality {
                get {
                    return quality;
                }
                set {
                    // Validate the value, it can't be less than 0 and not more than 100.if (value >= 0 && value <= 100)
                    {
                        quality = value;
                    }
                    else {
                        // Set the quality to a default value of 85% when an invalid value was specified.quality = value > 100 ? 100 : 85;
                    }
                }
            }
            [JsonProperty("Enable logging file")]
            public bool FileLogging {
                get;
                set;
            }
            [JsonProperty("Enable logging console")]
            public bool ConsoleLogging {
                get;
                set;
            }
            [JsonProperty("Enable discord logging")]
            public bool Discordlogging {
                get;
                set;
            }
            [JsonProperty("Discord Webhook")]
            public string DiscordWebhook {
                get;
                set;
            }
            [JsonProperty("Avatar URL")]
            public string AvatarUrl {
                get;
                set;
            }
            [JsonProperty("Discord Username")]
            public string DiscordUsername {
                get;
                set;
            }
            [JsonIgnore]
            public float MaxFileSizeInBytes {
                get {
                    return MaxSize * 1024 * 1024;
                }
            }
            private int quality = 85;
            /// <summary>
            /// Creates a default configuration file
            /// </summary>
            /// <returns>Default config</returns>
            public static SignArtistConfig DefaultConfig() {
                return new SignArtistConfig {
                    Cooldown = 0, MaxSize = 1, MaxDistance = 3, MaxActiveDownloads = 5, EnforceJpeg = false, Quality = 85, FileLogging = false, ConsoleLogging = false, Discordlogging = false, DiscordWebhook = "", AvatarUrl = "https://i.imgur.com/dH7V1Dh.png", DiscordUsername = "Sign Artist"
                }
                ;
            }
        }
        /// <summary>
        /// A type used to request new images to download./// </summary>
        private class DownloadRequest {
            public BasePlayer Sender {
                get;
            }
            public IPaintableEntity Sign {
                get;
            }
            public string Url {
                get;
                set;
            }
            public bool Raw {
                get;
            }
            public bool Hor {
                get;
            }
            /// <summary>
            /// Initializes a new instance of the <see cref="DownloadRequest" /> class./// </summary>
            /// <param name="url">The URL to download the image from.</param>
            /// <param name="player">The player that requested the download.</param>
            /// <param name="sign">The sign to add the image to.</param>
            /// <param name="raw">Should the image be stored with or without conversion to jpeg.</param>
            public DownloadRequest(string url, BasePlayer player, IPaintableEntity sign, bool raw, bool hor) {
                Url = url;
                Sender = player;
                Sign = sign;
                Raw = raw;
                Hor = hor;
            }
        }
        /// <summary>
        /// A type used to request new images to be restored./// </summary>
        private class RestoreRequest {
            public BasePlayer Sender {
                get;
            }
            public IPaintableEntity Sign {
                get;
            }
            public bool Raw {
                get;
            }
            /// <summary>
            /// Initializes a new instance of the <see cref="RestoreRequest" /> class./// </summary>
            /// <param name="player">The player that requested the restore.</param>
            /// <param name="sign">The sign to restore the image from.</param>
            /// <param name="raw">Should the image be stored with or without conversion to jpeg.</param>
            public RestoreRequest(BasePlayer player, IPaintableEntity sign, bool raw) {
                Sender = player;
                Sign = sign;
                Raw = raw;
            }
        }
        /// <summary>
        /// A type used to determine the size of the image for a sign
        /// </summary>
        public class ImageSize {
            public int Width {
                get;
            }
            public int Height {
                get;
            }
            public int ImageWidth {
                get;
            }
            public int ImageHeight {
                get;
            }
            /// <summary>
            /// Initializes a new instance of the <see cref="ImageSize" /> class./// </summary>
            /// <param name="width">The width of the canvas and the image.</param>
            /// <param name="height">The height of the canvas and the image.</param>
            public ImageSize(int width, int height) : this(width, height, width, height) {
            }
            /// <summary>
            /// Initializes a new instance of the <see cref="ImageSize" /> class./// </summary>
            /// <param name="width">The width of the canvas.</param>
            /// <param name="height">The height of the canvas.</param>
            /// <param name="imageWidth">The width of the image.</param>
            /// <param name="imageHeight">The height of the image.</param>
            public ImageSize(int width, int height, int imageWidth, int imageHeight) {
                Width = width;
                Height = height;
                ImageWidth = imageWidth;
                ImageHeight = imageHeight;
            }
        }
#region Image Download Behaviour
        /// <summary>
        /// UnityEngine script to be attached to a GameObject to download images and apply them to signs./// </summary>
        private class ImageDownloader : MonoBehaviour {
            private byte activeDownloads;
            private byte activeRestores;
            private readonly SignArtist signArtist = (SignArtist)Interface.Oxide.RootPluginManager.GetPlugin(nameof(SignArtist));
            private readonly Queue<DownloadRequest> downloadQueue = new Queue<DownloadRequest>();
            private readonly Queue<RestoreRequest> restoreQueue = new Queue<RestoreRequest>();
            /// <summary>
            /// Queue a new image to download and add to a sign
            /// </summary>
            /// <param name="url">The URL to download the image from.</param>
            /// <param name="player">The player that requested the download.</param>
            /// <param name="sign">The sign to add the image to.</param>
            /// <param name="raw">Should the image be stored with or without conversion to jpeg.</param>
            public void QueueDownload(string url, BasePlayer player, IPaintableEntity sign, bool raw, bool hor = false) {
                // Check if there is already a request for this sign and show an error if there is.bool existingRequest = downloadQueue.Any(request => request.Sign == sign) || restoreQueue.Any(request => request.Sign == sign);
                if (existingRequest) {
                    signArtist.SendMessage(player, "ActionQueuedAlready");
                    return;
                }
                // Instantiate a new DownloadRequest and add it to the queue.downloadQueue.Enqueue(new DownloadRequest(url, player, sign, raw, hor));
                // Attempt to start the next download.StartNextDownload();
            }
            /// <summary>
            /// Attempts to restore a sign./// </summary>
            /// <param name="player">The player that requested the restore.</param>
            /// <param name="sign">The sign to restore the image from.</param>
            /// <param name="raw">Should the image be stored with or without conversion to jpeg.</param>
            public void QueueRestore(BasePlayer player, IPaintableEntity sign, bool raw) {
                // Check if there is already a request for this sign and show an error if there is.bool existingRequest = downloadQueue.Any(request => request.Sign == sign) || restoreQueue.Any(request => request.Sign == sign);
                if (existingRequest) {
                    signArtist.SendMessage(player, "ActionQueuedAlready");
                    return;
                }
                // Instantiate a new RestoreRequest and add it to the queue.restoreQueue.Enqueue(new RestoreRequest(player, sign, raw));
                // Attempt to start the next restore.StartNextRestore();
            }
            /// <summary>
            /// Starts the next download if available./// </summary>
            /// <param name="reduceCount"></param>
            private void StartNextDownload(bool reduceCount = false) {
                // Check if we need to reduce the active downloads counter after a succesful or failed download.if (reduceCount)
                {
                    activeDownloads--;
                }
                // Check if we don't have the maximum configured amount of downloads running already.if (activeDownloads >= signArtist.Settings.MaxActiveDownloads)
                {
                    return;
                }
                // Check if there is still an image in the queue.if (downloadQueue.Count <= 0)
                {
                    return;
                }
                // Increment the active downloads by 1 and start the download process.activeDownloads++;
                StartCoroutine(DownloadImage(downloadQueue.Dequeue()));
            }
            /// <summary>
            /// Starts the next restore if available./// </summary>
            /// <param name="reduceCount"></param>
            private void StartNextRestore(bool reduceCount = false) {
                // Check if we need to reduce the active restores counter after a succesful or failed restore.if (reduceCount)
                {
                    activeRestores--;
                }
                // Check if we don't have the maximum configured amount of restores running already.if (activeRestores >= signArtist.Settings.MaxActiveDownloads)
                {
                    return;
                }
                // Check if there is still an image in the queue.if (restoreQueue.Count <= 0)
                {
                    return;
                }
                // Increment the active restores by 1 and start the restore process.activeRestores++;
                StartCoroutine(RestoreImage(restoreQueue.Dequeue()));
            }
            /// <summary>
            /// Downloads the image and adds it to the sign./// </summary>
            /// <param name="request">The requested <see cref="DownloadRequest"/> instance.</param>
            private IEnumerator DownloadImage(DownloadRequest request) {
                if (ItemManager.itemDictionaryByName.ContainsKey(request.Url)) {
                    request.Url = string.Format(ItemIconUrl, request.Url);
                }
                UnityWebRequest www = UnityWebRequest.Get(request.Url);
                yield return www.SendWebRequest();
                // Verify that there is a valid reference to the plugin from this class.if (signArtist == null)
                {
                    throw new NullReferenceException("signArtist");
                }
                // Verify that the webrequest was succesful.if (www.isNetworkError || www.isHttpError)
                {
                    // The webrequest wasn't succesful, show a message to the player and attempt to start the next download.signArtist.SendMessage(request.Sender, "WebErrorOccurred", www.error);
                    www.Dispose();
                    StartNextDownload(true);
                    yield break;
                }
                // Verify that the file doesn't exceed the maximum configured filesize.if (www.downloadedBytes > signArtist.Settings.MaxFileSizeInBytes)
                {
                    // The file is too large, show a message to the player and attempt to start the next download.signArtist.SendMessage(request.Sender, "FileTooLarge", signArtist.Settings.MaxSize);
                    www.Dispose();
                    StartNextDownload(true);
                    yield break;
                }
                // Get the bytes array for the image from the webrequest and lookup the target image size for the targeted sign.byte[] imageBytes;
                if (request.Raw) {
                    imageBytes = www.downloadHandler.data;
                }
                else {
                    imageBytes = GetImageBytes(www);
                }
                ImageSize size = GetImageSizeFor(request.Sign);
                // Verify that we have image size data for the targeted sign.if (size == null)
                {
                    // No data was found, show a message to the player and print a detailed message to the server console and attempt to start the next download.signArtist.SendMessage(request.Sender, "ErrorOccurred");
                    signArtist.PrintWarning($"Couldn't find the required image size for {request.Sign.PrefabName}, please report this in the plugin's thread.");
                    StartNextDownload(true);
                    www.Dispose();
                    yield break;
                }
                RotateFlipType rotation = RotateFlipType.RotateNoneFlipNone;
                if (request.Hor) {
                    rotation = RotateFlipType.RotateNoneFlipX;
                }
                object rotateObj = Interface.Call("GetImageRotation", request.Sign.Entity);
                if (rotateObj is RotateFlipType) {
                    rotation = (RotateFlipType)rotateObj;
                }
                // Get the bytes array for the resized image for the targeted sign.byte[] resizedImageBytes = imageBytes.ResizeImage(size.Width, size.Height, size.ImageWidth, size.ImageHeight, signArtist.Settings.EnforceJpeg && !request.Raw, rotation);
                // Verify that the resized file doesn't exceed the maximum configured filesize.if (resizedImageBytes.Length > signArtist.Settings.MaxFileSizeInBytes)
                {
                    // The file is too large, show a message to the player and attempt to start the next download.signArtist.SendMessage(request.Sender, "FileTooLarge", signArtist.Settings.MaxSize);
                    www.Dispose();
                    StartNextDownload(true);
                    yield break;
                }
                // Check if the sign already has a texture assigned to it.if (request.Sign.TextureId() > 0)
                {
                    // A texture was already assigned, remove this file to make room for the new one.FileStorage.server.RemoveExact(request.Sign.TextureId(), FileStorage.Type.png, request.Sign.NetId, request.Sign.FrameId());
                }
                // Create the image on the filestorage and send out a network update for the sign.request.Sign.SetImage(FileStorage.server.Store(resizedImageBytes, FileStorage.Type.png, request.Sign.NetId, request.Sign.FrameId()));
                request.Sign.SendNetworkUpdate();
                // Notify the player that the image was loaded.signArtist.SendMessage(request.Sender, "ImageLoaded");
                // Call the Oxide hook 'OnSignUpdated' to notify other plugins of the update event.Interface.Oxide.CallHook("OnSignUpdated", request.Sign, request.Sender);
                if (request.Sender != null) {
                    // Check if logging to console is enabled.if (signArtist.Settings.ConsoleLogging)
                    {
                        // Console logging is enabled, show a message in the server console.signArtist.Puts(signArtist.GetTranslation("LogEntry"), request.Sender.displayName,
                        request.Sender.userID, request.Sign.TextureId(), request.Sign.ShortPrefabName, request.Url);
                    }
                    // Check if logging to file is enabled.if (signArtist.Settings.FileLogging)
                    {
                        // File logging is enabled, add an entry to the logfile.signArtist.LogToFile("log",
                        string.Format(signArtist.GetTranslation("LogEntry"), request.Sender.displayName, request.Sender.userID, request.Sign.TextureId(), request.Sign.ShortPrefabName, request.Url), signArtist);
                    }
                    if (signArtist.Settings.Discordlogging) {
                        // Discord logging is enabled, add an entry to the logfile.StartCoroutine(LogToDiscord(request));
                    }
                }
                // Attempt to start the next download.StartNextDownload(true);
                www.Dispose();
            }
            private IEnumerator LogToDiscord(DownloadRequest request) {
                BasePlayer player = request.Sender;
                IPaintableEntity sign = request.Sign;
                var msg = DiscordMessage(ConVar.Server.hostname, player.displayName, player.UserIDString, sign.ShortPrefabName, request.Url, sign.Entity.transform.position.ToString());
                string jsonmsg = JsonConvert.SerializeObject(msg);
                UnityWebRequest wwwpost = new UnityWebRequest(signArtist.Settings.DiscordWebhook, "POST");
                byte[] jsonToSend = new System.Text.UTF8Encoding().GetBytes(jsonmsg.ToString());
                wwwpost.uploadHandler = (UploadHandler)new UploadHandlerRaw(jsonToSend);
                wwwpost.SetRequestHeader("Content-Type", "application/json");
                yield return wwwpost.SendWebRequest();
                if (wwwpost.isNetworkError || wwwpost.isHttpError) {
                    signArtist.PrintError(wwwpost.error);
                    signArtist.PrintError(jsonmsg);
                    yield break;
                }
                wwwpost.Dispose();
            }
            private Message DiscordMessage(string servername, string playername, string userid, string itemname, string imgurl, string location) {
                string steamprofile = "https://steamcommunity.com/profiles/" + userid;
                var fields = new List<Message.Fields>() {
                    new Message.Fields("Player: " + playername, $"[{userid}]({steamprofile})", true), new Message.Fields("Entity", itemname, true), new Message.Fields("Image Url", imgurl, false), new Message.Fields("Teleport position", "teleportpos " + location.Replace(" ", string.Empty), false)
                }
                ;
                var footer = new Message.Footer($"Logged @{DateTime.UtcNow:dd/MM/yy HH:mm:ss}");
                var image = new Message.Image(imgurl);
                var embeds = new List<Message.Embeds>() {
                    new Message.Embeds("Server - " + servername, "A sign has been updated" , fields, footer, image)
                }
                ;
                Message msg = new Message(signArtist.Settings.DiscordUsername, signArtist.Settings.AvatarUrl, embeds);
                return msg;
            }
            /// <summary>
            /// Restores the image and adds it to the sign again./// </summary>
            /// <param name="request">The requested <see cref="RestoreRequest"/> instance.</param>
            /// <returns></returns>
            private IEnumerator RestoreImage(RestoreRequest request) {
                // Verify that there is a valid reference to the plugin from this class.if (signArtist == null)
                {
                    throw new NullReferenceException("signArtist");
                }
                byte[] imageBytes;
                // Check if the sign already has a texture assigned to it.if (request.Sign.TextureId() == 0)
                {
                    // No texture was previously assigned, show a message to the player.signArtist.SendMessage(request.Sender, "RestoreErrorOccurred");
                    StartNextRestore(true);
                    yield break;
                }
                // Cache the byte array of the currently stored file.imageBytes = FileStorage.server.Get(request.Sign.TextureId(), FileStorage.Type.png, request.Sign.NetId);
                ImageSize size = GetImageSizeFor(request.Sign);
                // Verify that we have image size data for the targeted sign.if (size == null)
                {
                    // No data was found, show a message to the player and print a detailed message to the server console and attempt to start the next download.signArtist.SendMessage(request.Sender, "ErrorOccurred");
                    signArtist.PrintWarning($"Couldn't find the required image size for {request.Sign.PrefabName}, please report this in the plugin's thread.");
                    StartNextRestore(true);
                    yield break;
                }
                // Remove the texture from the FileStorage.FileStorage.server.Remove(request.Sign.TextureId(), FileStorage.Type.png, request.Sign.NetId);
                // Get the bytes array for the resized image for the targeted sign.byte[] resizedImageBytes = imageBytes.ResizeImage(size.Width, size.Height, size.ImageWidth, size.ImageHeight, signArtist.Settings.EnforceJpeg && !request.Raw);
                // Create the image on the filestorage and send out a network update for the sign.request.Sign.SetImage(FileStorage.server.Store(resizedImageBytes, FileStorage.Type.png, request.Sign.NetId));
                request.Sign.SendNetworkUpdate();
                // Notify the player that the image was loaded.signArtist.SendMessage(request.Sender, "ImageRestored");
                // Call the Oxide hook 'OnSignUpdated' to notify other plugins of the update event.Interface.Oxide.CallHook("OnSignUpdated", request.Sign, request.Sender);
                // Attempt to start the next download.StartNextRestore(true);
            }
            /// <summary>
            /// Gets the target image size for a <see cref="Signage"/>./// </summary>
            /// <param name="signage"></param>
            private ImageSize GetImageSizeFor(IPaintableEntity signage) {
                if (signArtist.ImageSizePerAsset.ContainsKey(signage.ShortPrefabName)) {
                    return signArtist.ImageSizePerAsset[signage.ShortPrefabName];
                }
                return null;
            }
            /// <summary>
            /// Converts the <see cref="Texture2D"/> from the webrequest to a <see cref="byte"/> array./// </summary>
            /// <param name="www">The completed webrequest.</param>
            private byte[] GetImageBytes(UnityWebRequest www) {
                Texture2D texture = new Texture2D(2, 2);
                texture.LoadImage(www.downloadHandler.data);
                byte[] image;
                if (texture.format == TextureFormat.ARGB32 && !signArtist.Settings.EnforceJpeg) {
                    image = texture.EncodeToPNG();
                }
                else {
                    image = texture.EncodeToJPG(signArtist.Settings.Quality);
                }
                DestroyImmediate(texture);
                return image;
            }
        }
#endregion Image Download Behaviour
        private interface IBasePaintableEntity {
            BaseEntity Entity {
                get;
            }
            string PrefabName {
                get;
            }
            string ShortPrefabName {
                get;
            }
            uint NetId {
                get;
            }
            void SendNetworkUpdate();
        }
        private interface IPaintableEntity : IBasePaintableEntity {
            void SetImage(uint id);
            bool CanUpdate(BasePlayer player);
            uint TextureId();
            uint FrameId();
        }
        private class BasePaintableEntity : IBasePaintableEntity {
            public BaseEntity Entity {
                get;
            }
            public string PrefabName {
                get;
            }
            public string ShortPrefabName {
                get;
            }
            public uint NetId {
                get;
            }
            protected BasePaintableEntity(BaseEntity entity) {
                Entity = entity;
                PrefabName = Entity.PrefabName;
                ShortPrefabName = Entity.ShortPrefabName;
                NetId = Entity.net.ID;
            }
            public void SendNetworkUpdate() {
                Entity.SendNetworkUpdate();
            }
        }
        private class NeonSignage : BasePaintableEntity, IPaintableEntity {
            public Signage Sign {
                get;
                set;
            }
            public int Frame {
                get;
                set;
            }
            public NeonSignage(Signage sign, int frame) : base(sign) {
                Sign = sign;
                if (frame >= sign.paintableSources.Length) {
                    Frame = sign.paintableSources.Length - 1;
                }
                else if (frame < 1) {
                    Frame = 0;
                }
                else {
                    Frame = frame - 1;
                }
            }
            public void SetImage(uint id) {
                Sign.textureIDs[Frame] = id;
            }
            public bool CanUpdate(BasePlayer player) {
                return Sign.CanUpdateSign(player);
            }
            public uint TextureId() {
                return Sign.textureIDs[Frame];
            }
            public uint FrameId() {
                return (uint)Frame;
            }
        }
        private class PaintableSignage : BasePaintableEntity, IPaintableEntity {
            public Signage Sign {
                get;
                set;
            }
            public PaintableSignage(Signage sign) : base(sign) {
                Sign = sign;
            }
            public void SetImage(uint id) {
                Sign.textureIDs = new uint[] {
                    id
                }
                ;
            }
            public bool CanUpdate(BasePlayer player) {
                return Sign.CanUpdateSign(player);
            }
            public uint TextureId() {
                return Sign.textureIDs.First();
            }
            public uint FrameId() {
                return 0;
            }
        }
        private class PaintableFrame : BasePaintableEntity, IPaintableEntity {
            public PhotoFrame Sign {
                get;
                set;
            }
            public PaintableFrame(PhotoFrame sign) : base(sign) {
                Sign = sign;
            }
            public void SetImage(uint id) {
                Sign._overlayTextureCrc = id;
            }
            public bool CanUpdate(BasePlayer player) {
                return Sign.CanUpdateSign(player);
            }
            public uint TextureId() {
                return Sign._overlayTextureCrc;
            }
            public uint FrameId() {
                return 0;
            }
        }
#region Init
        /// <summary>
        /// Oxide hook that is triggered when the plugin is loaded./// </summary>
        ///
        private void Init() {
            // Register all the permissions used by the plugin
            permission.RegisterPermission("signartist.file", this);
            permission.RegisterPermission("signartist.ignorecd", this);
            permission.RegisterPermission("signartist.ignoreowner", this);
            permission.RegisterPermission("signartist.raw", this);
            permission.RegisterPermission("signartist.restore", this);
            permission.RegisterPermission("signartist.restoreall", this);
            permission.RegisterPermission("signartist.text", this);
            permission.RegisterPermission("signartist.url", this);
            AddCovalenceCommand("sil", "SilCommand");
            AddCovalenceCommand("silt", "SiltCommand");
            AddCovalenceCommand("sili", "SilItemCommand");
            AddCovalenceCommand("silrestore", "RestoreCommand");
            // Initialize the dictionary with all paintable object assets and their target sizes
            ImageSizePerAsset = new Dictionary<string, ImageSize> {
                // Picture Frames
                ["sign.pictureframe.landscape"]
                = new ImageSize(256, 128),  // Landscape Picture Frame
                ["sign.pictureframe.portrait"]
                = new ImageSize(128, 256),  // Portrait Picture Frame
                ["sign.pictureframe.tall"]
                = new ImageSize(128, 512),  // Tall Picture Frame
                ["sign.pictureframe.xl"]
                = new ImageSize(512, 512),  // XL Picture Frame
                ["sign.pictureframe.xxl"]
                = new ImageSize(1024, 512),  // XXL Picture Frame
                // Wooden Signs
                ["sign.small.wood"]
                = new ImageSize(128, 64),  // Small Wooden Sign
                ["sign.medium.wood"]
                = new ImageSize(256, 128),  // Wooden Sign
                ["sign.large.wood"]
                = new ImageSize(256, 128),  // Large Wooden Sign
                ["sign.huge.wood"]
                = new ImageSize(512, 128),  // Huge Wooden Sign
                // Banners
                ["sign.hanging.banner.large"]
                = new ImageSize(64, 256),  // Large Banner Hanging
                ["sign.pole.banner.large"]
                = new ImageSize(64, 256),  // Large Banner on Pole
                // Hanging Signs
                ["sign.hanging"]
                = new ImageSize(128, 256),  // Two Sided Hanging Sign
                ["sign.hanging.ornate"]
                = new ImageSize(256, 128),  // Two Sided Ornate Hanging Sign
                // Town Signs
                ["sign.post.single"]
                = new ImageSize(128, 64),  // Single Sign Post
                ["sign.post.double"]
                = new ImageSize(256, 256),  // Double Sign Post
                ["sign.post.town"]
                = new ImageSize(256, 128),  // One Sided Town Sign Post
                ["sign.post.town.roof"]
                = new ImageSize(256, 128),  // Two Sided Town Sign Post
                ["photoframe.large"]
                = new ImageSize(320, 240), ["photoframe.portrait"] = new ImageSize(320, 384), ["photoframe.landscape"] = new ImageSize(320, 240), ["sign.neon.125x215"] = new ImageSize(125, 215), ["sign.neon.125x125"] = new ImageSize(125, 125), ["sign.neon.xl"] = new ImageSize(256, 256), ["sign.neon.xl.animated"] = new ImageSize(256, 256), ["sign.neon.125x215.animated"] = new ImageSize(125, 215),  // Other paintable assets
                ["spinner.wheel.deployed"]
                = new ImageSize(512, 512, 285, 285),  // Spinning Wheel
            }
            ;
        }
        private void GetSteamworksImages() {
            foreach (InventoryDef item in Steamworks.SteamInventory.Definitions) {
                string shortname = item.GetProperty("itemshortname");
                if (item == null || string.IsNullOrEmpty(shortname)) continue;
                if (item.Id < 100) continue;
                ulong workshopid;
                if (!ulong.TryParse(item.GetProperty("workshopid"), out workshopid)) continue;
                if (string.IsNullOrEmpty(item.IconUrl)) continue;
                SkiniconUrls[workshopid] = item.IconUrl;
            }
        }
        /// <summary>
        /// Oxide hook that is triggered to automatically load the configuration file./// </summary>
        protected override void LoadConfig() {
            base.LoadConfig();
            Settings = Config.ReadObject<SignArtistConfig>();
            SaveConfig();
        }
        /// <summary>
        /// Oxide hook that is triggered to automatically load the default configuration file when no file exists./// </summary>
        protected override void LoadDefaultConfig() {
            Settings = SignArtistConfig.DefaultConfig();
        }
        /// <summary>
        /// Oxide hook that is triggered to save the configuration file./// </summary>
        protected override void SaveConfig() {
            Config.WriteObject(Settings);
        }
        /// <summary>
        /// Oxide hook that is triggered when the server has fully initialized./// </summary>
        private void OnServerInitialized() {
            // Create a new GameObject and attach the UnityEngine script to it for handling the image downloads.imageDownloaderGameObject = new GameObject("ImageDownloader");
            imageDownloader = imageDownloaderGameObject.AddComponent<ImageDownloader>();
            if ((Steamworks.SteamInventory.Definitions?.Length ?? 0) == 0) {
                PrintWarning("Waiting for Steamworks to update item definitions....");
                Steamworks.SteamInventory.OnDefinitionsUpdated += GetSteamworksImages;
            }
            else GetSteamworksImages();
        }
        /// <summary>
        /// Oxide hook that is triggered when the plugin is unloaded./// </summary>
        private void Unload() {
            // Destroy the created GameObject and cleanup.UnityEngine.Object.Destroy(imageDownloaderGameObject);
            imageDownloader = null;
            cooldowns = null;
            Steamworks.SteamInventory.OnDefinitionsUpdated -= GetSteamworksImages;
        }
        /// <summary>
        /// Handles the /sil command./// </summary>
        /// <param name="iplayer">The player that has executed the command.</param>
        /// <param name="command">The name of the command that was executed.</param>
        /// <param name="args">All arguments that were passed with the command.</param>
        ///
#endregion Init
#region Localization
        /// <summary>
        /// Oxide hook that is triggered automatically after it has been loaded to initialize the messages for the Lang API./// </summary>
        protected override void LoadDefaultMessages() {
            // Register all messages used by the plugin in the Lang API.lang.RegisterMessages(new Dictionary<string, string>
            {
                // Messages used throughout the plugin.["WebErrorOccurred"] = "Failed to download the image! Error {0}.",
                ["FileTooLarge"]
                = "The file exceeds the maximum file size of {0}Mb.", ["ErrorOccurred"] = "An unknown error has occured, if this error keeps occuring please notify the server admin.", ["RestoreErrorOccurred"] = "Can't restore the sign because no texture is assigned to it.", ["DownloadQueued"] = "Your image was added to the download queue!", ["RestoreQueued"] = "Your sign was added to the restore queue!", ["RestoreBatchQueued"] = "You added all {0} signs to the restore queue!", ["ImageLoaded"] = "The image was succesfully loaded to the sign!", ["ImageRestored"] = "The image was succesfully restored for the sign!", ["LogEntry"] = "Player `{0}` (SteamId: {1}) loaded {2} into {3} from {4}", ["NoSignFound"] = "Unable to find a sign! Make sure you are looking at one and that you are not too far away from it.", ["Cooldown"] = "You can't use the command yet! Remaining cooldown: {0}.", ["SignNotOwned"] = "You can't change this sign as it is protected by a tool cupboard.", ["NoItemHeld"] = "You're not holding an item.", ["ActionQueuedAlready"] = "An action has already been queued for this sign, please wait for this action to complete.", ["SyntaxSilCommand"] = "Syntax error!\nSyntax: /sil [frame] <url> [raw]", ["SyntaxSiltCommand"] = "Syntax error!\nSyntax: /silt <message> [<fontsize:number>] [<color:hex value>] [<bgcolor:hex value>] [raw]", ["NoPermission"] = "You don't have permission to use this command.", ["NoPermissionFile"] = "You don't have permission to use images from the server's filesystem.", ["NoPermissionRaw"] = "You don't have permission to use raw images, loading normally instead.", ["NoPermissionRestoreAll"] = "You don't have permission to use restore all signs at once.",  // Cooldown formatting 'translations'.["day"] = "day",
                ["days"]
                = "days", ["hour"] = "hour", ["hours"] = "hours", ["minute"] = "minute", ["minutes"] = "minutes", ["second"] = "second", ["seconds"] = "seconds", ["and"] = "and"
            }
            , this);
        }
#endregion Localization
#region Commands
        [Command("sil"), Permission("signartist.url")]
        private void SilCommand(IPlayer iplayer, string command, string[] args) {
            var player = iplayer.Object as BasePlayer;
            // Verify if the correct syntax is used.if (args.Length < 1)
            {
                // Invalid syntax was used, show an error message to the player.SendMessage(player, "SyntaxSilCommand");
                return;
            }
            // Verify if the player has permission to use this command.if (!HasPermission(player, "signartist.url"))
            {
                // The player doesn't have permission to use this command, show an error message.SendMessage(player, "NoPermission");
                return;
            }
            // Verify that the command isn't on cooldown for the user.if (HasCooldown(player))
            {
                // The command is still on cooldown for the player, show an error message.SendMessage(player, "Cooldown", FormatCooldown(GetCooldown(player)));
                return;
            }
            int frame = 0;
            string url = ((args.Length > 1) && int.TryParse(args[0], out frame)) ? args[1] : args[0];
            // Check if the player is looking at a sign.IPaintableEntity sign;
            if (!IsLookingAtSign(player, out sign, frame)) {
                // The player isn't looking at a sign or is too far away from it, show an error message.SendMessage(player, "NoSignFound");
                return;
            }
            // Check if the player is able to update the sign.if (!CanChangeSign(player, sign))
            {
                // The player isn't able to update the sign, show an error message.SendMessage(player, "SignNotOwned");
                return;
            }
            // Check if the player wants to add the image from the server's filesystem and has the permission to do so.if (url.StartsWith("file://") && !HasPermission(player, "signartist.file"))
            {
                // The player doesn't have permission for this, show an error message.SendMessage(player, "NoPermissionFile");
                return;
            }
            // Check if the player wants to add the image as a raw image and has the permission to do so.bool raw = ((args.Length > 2 && args[2].Equals("raw", StringComparison.OrdinalIgnoreCase)) || (args.Length > 1 && args[1].Equals("raw", StringComparison.OrdinalIgnoreCase)));
            if (raw && !HasPermission(player, "signartist.raw")) {
                // The player doesn't have permission for this, show a message and disable raw.SendMessage(player, "NoPermissionRaw");
                raw = false;
            }
            // This sign pastes in reverse, so we'll check and set a var to flip it
            bool hor = sign.ShortPrefabName == "sign.hanging";
            // Notify the player that it is added to the queue.SendMessage(player, "DownloadQueued");
            // Queue the download of the specified image.imageDownloader.QueueDownload(url, player, sign, raw, hor);
            // Call external hook
            Interface.Oxide.CallHook("OnImagePost", player, url);
            // Set the cooldown on the command for the player if the cooldown setting is enabled.SetCooldown(player);
        }
        [Command("sili"), Permission("signartist.url")]
        private void SilItemCommand(IPlayer iplayer, string command, string[] args) {
            var player = iplayer.Object as BasePlayer;
            if (!HasPermission(player, "signartist.url")) {
                SendMessage(player, "NoPermission");
                return;
            }
            if (HasCooldown(player)) {
                SendMessage(player, "Cooldown", FormatCooldown(GetCooldown(player)));
                return;
            }
            IPaintableEntity sign;
            if (!IsLookingAtSign(player, out sign)) {
                SendMessage(player, "NoSignFound");
                return;
            }
            if (!CanChangeSign(player, sign)) {
                SendMessage(player, "SignNotOwned");
                return;
            }
            Item held = player.GetActiveItem();
            if (held == null) {
                SendMessage(player, "NoItemHeld");
                return;
            }
            string shortname = held.info.shortname;
            bool hor = sign.ShortPrefabName == "sign.hanging";
            SendMessage(player, "DownloadQueued");
            bool defaultskin = false;
            if (args.Length == 1 && args[0] == "default") defaultskin = true;
            if (held.skin != 0uL && !defaultskin) {
                string url;
                if (SkiniconUrls.TryGetValue(held.skin, out url)) {
                    shortname = url;
                }
                else {
                    ServerMgr.Instance.StartCoroutine(DownloadWorkshopskin(held, sign, hor));
                    return;
                }
            }
            imageDownloader.QueueDownload(shortname, player, sign, false, hor);
            Interface.Oxide.CallHook("OnImagePost", player, shortname);
            SetCooldown(player);
        }
        private const string FindWorkshopSkinUrl = "https://api.steampowered.com/ISteamRemoteStorage/GetPublishedFileDetails/v1/";
        private IEnumerator DownloadWorkshopskin(Item held, IPaintableEntity sign, bool hor) {
            BasePlayer player = held.GetOwnerPlayer();
            WWWForm form = new WWWForm();
            form.AddField("itemcount", "1");
            form.AddField("publishedfileids[0]", held.skin.ToString());
            UnityWebRequest www = UnityWebRequest.Post(FindWorkshopSkinUrl, form);
            yield return www.SendWebRequest();
            string url = "";
            // Verify that the webrequest was succesful.if (www.isNetworkError || www.isHttpError)
            {
                // The webrequest wasn't succesful, show a message to the player and attempt to start the next download.PrintError(www.error.ToString());
                url = held.info.shortname;
            }
            var json = JsonConvert.DeserializeObject<GetPublishedFileDetailsClass>(www.downloadHandler.text);
            url = json.response.publishedfiledetails[0].preview_url;
            imageDownloader.QueueDownload(url, player, sign, false, hor);
            Interface.Oxide.CallHook("OnImagePost", player, held.info.shortname);
            SetCooldown(player);
        }
        /// <summary>
        /// Handles the /silt command
        /// </summary>
        /// <param name="iplayer">The player that has executed the command.</param>
        /// <param name="command">The name of the command that was executed.</param>
        /// <param name="args">All arguments that were passed with the command.</param>
        [Command("silt"), Permission("signartist.text")]
        private void SiltCommand(IPlayer iplayer, string command, string[] args) {
            var player = iplayer.Object as BasePlayer;
            // Verify if the correct syntax is used.if (args.Length < 1)
            {
                // Invalid syntax was used, show an error message to the player.SendMessage(player, "SyntaxSiltCommand");
                return;
            }
            // Verify if the player has permission to use this command.if (!HasPermission(player, "signartist.text"))
            {
                // The player doesn't have permission to use this command, show an error message.SendMessage(player, "NoPermission");
                return;
            }
            // Verify that the command isn't on cooldown for the user.if (HasCooldown(player))
            {
                // The command is still on cooldown for the player, show an error message.SendMessage(player, "Cooldown", FormatCooldown(GetCooldown(player)));
                return;
            }
            // Check if the player is looking at a sign.IPaintableEntity sign;
            if (!IsLookingAtSign(player, out sign)) {
                // The player isn't looking at a sig
// ... [Code preview truncated due to length. Full source in attached file] ...

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

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

Сверху