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

FREE TrophySigns : 0.2.1 0.2.1

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

namespace Oxide.Plugins
{
    [Info("TrophySigns", "k1lly0u", "0.2.1")]
    [Description("Collect human skulls and mount them to signs and spears in your base")]
    class TrophySigns : RustPlugin
    {
        #region Fields        
        private StoredData storedData;

        private DynamicConfigFile data;
                
        private bool wipeDetected;

        private Hash<Signage, DroppedItem> signRegisteredSkulls = new Hash<Signage, DroppedItem>();

        private Hash<DroppedItem, List<DroppedItem>> spearRegisteredSkulls = new Hash<DroppedItem, List<DroppedItem>>();

        private ImageStorage imageStorage;

        private static TrophySigns Instance { get; set; }

        private const int TARGET_LAYERS = (1 << 0 | 1 << 8 | 1 << 16 | 1 << 21 | 1 << 23 | 1 << 26);

        private const string BURLAPSACK_PREFAB = "assets/prefabs/misc/burlap sack/generic_world.prefab";

        private const int SKULL_ITEM_ID = 996293980;
        #endregion

        #region Oxide Hooks
        private void Loaded()
        {
            permission.RegisterPermission("trophysigns.use", this);
            lang.RegisterMessages(Messages, this);
            data = Interface.Oxide.DataFileSystem.GetFile("trophysigns_data");
        }

        private void OnServerInitialized()
        {
            Instance = this;

            imageStorage = new GameObject().AddComponent<ImageStorage>();

            LoadData();

            if (wipeDetected)
            {
                storedData = new StoredData();
                SaveData();
            }

            ServerMgr.Instance.StartCoroutine(FindRegisteredSignage(BaseNetworkable.serverEntities.Where(x => x is Signage).Cast<Signage>()));
        }

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

        private void OnEntityKill(BaseNetworkable networkable)
        {
            Signage signage = networkable.GetComponent<Signage>();
            if (signage != null)
            {
                if (signRegisteredSkulls.ContainsKey(signage))
                    signRegisteredSkulls.Remove(signage);
            }
        }

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

        private void OnServerSave() => SaveData();

        private void OnActiveItemChanged(BasePlayer player, Item olditem, Item item)
        {
            if (player == null || item == null || !permission.UserHasPermission(player.UserIDString, "trophysigns.use"))
                return;

            if (!CanPlace(player))
                return;

            if (item.info.itemid == SKULL_ITEM_ID && !player.GetComponent<ItemPlacement>())
                player.gameObject.AddComponent<ItemPlacement>();
        }

        private object OnItemPickup(Item item, BasePlayer player)
        {
            if (item != null && player != null)
            {
                ItemPlacement placement = player.GetComponent<ItemPlacement>();
                if (placement != null)
                    return false;
                else
                {
                    DroppedItem droppedItem = item.GetWorldEntity()?.GetComponent<DroppedItem>();

                    if (droppedItem == null)
                        return null;

                    List<DroppedItem> skulls;

                    if (spearRegisteredSkulls.TryGetValue(droppedItem, out skulls))
                    {
                        if (skulls?.Count == 0)
                        {
                            if (!CanRemove(player, "Error.NoBuildingAuthSpear"))
                                return false;

                            Pool.FreeList(ref skulls);

                            spearRegisteredSkulls.Remove(droppedItem);
                        }
                        else
                        {
                            SendReply(player, msg("Error.SkullsOnSpear", player.userID));
                            return false;
                        }
                    }

                    if (droppedItem.item.info.itemid == SKULL_ITEM_ID)
                    {
                        Signage signage = droppedItem.GetComponentInParent<Signage>();

                        if (signage != null && signRegisteredSkulls.ContainsKey(signage))
                        {
                            if (!CanRemove(player, "Error.NoBuildingAuthSkull"))
                                return false;

                            signRegisteredSkulls.Remove(signage);

                            if (signage.HasFlag(BaseEntity.Flags.Locked))
                                signage.SetFlag(BaseEntity.Flags.Locked, false);

                            UpdateSignImage(signage, "", true);
                        }
                        else
                        {
                            if (droppedItem.HasParent())
                            {
                                DroppedItem spear = droppedItem.GetParentEntity().GetComponent<DroppedItem>();
                                if (spear == null)
                                    return null;

                                if (spearRegisteredSkulls.TryGetValue(spear, out skulls) && skulls.Contains(droppedItem))
                                {
                                    if (!CanRemove(player, "Error.NoBuildingAuthSkull"))
                                        return false;

                                    spearRegisteredSkulls[spear].Remove(droppedItem);
                                }
                            }
                        }
                    }
                }
            }
            return null;
        }

        private void Unload()
        {
            if (!ServerMgr.Instance.Restarting)
                SaveData();

            ItemPlacement[] placementComps = UnityEngine.Object.FindObjectsOfType<ItemPlacement>();
            if (placementComps != null)
            {
                foreach (ItemPlacement placement in placementComps)
                    placement.CancelPlacement();
            }

            for (int i = signRegisteredSkulls.Count - 1; i >= 0; i--)
            {
                DroppedItem skullItem = signRegisteredSkulls.ElementAt(i).Value;
                skullItem?.DestroyItem();
                if (skullItem != null && !skullItem.IsDestroyed)
                    skullItem.Kill();
            }

            for (int i = 0; i < spearRegisteredSkulls.Count; i++)
            {
                KeyValuePair<DroppedItem, List<DroppedItem>> kvp = spearRegisteredSkulls.ElementAt(i);

                DroppedItem spear = kvp.Key;
                List<DroppedItem> skulls = kvp.Value;

                if (spear == null)
                    continue;

                for (int y = 0; y < skulls.Count; y++)
                {
                    DroppedItem skullItem = skulls[y];
                    if (skullItem != null)
                    {
                        skullItem.DestroyItem();
                        if (skullItem != null && !skullItem.IsDestroyed)
                            skullItem.Kill();
                    }
                }

                Pool.FreeList(ref skulls);

                spear.DestroyItem();

                if (!spear.IsDestroyed)
                    spear.Kill();
            }

            configData = null;
            Instance = null;
        }
        #endregion
      
        #region Initialization  
        private IEnumerator FindRegisteredSignage(IEnumerable<Signage> signage)
        {
            for (int i = 0; i < signage.Count(); i++)
            {
                Signage sign = signage.ElementAt(i);

                if (sign == null || sign.IsDestroyed || !storedData.data.ContainsKey(sign.net.ID))
                    continue;

                StoredData.TrophyData data = storedData.data[sign.net.ID];                
                                
                InitializeSign(sign, data.displayName, data.Position, data.Rotation);

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

            yield return ServerMgr.Instance.StartCoroutine(CreateAndPopulateSpears());
        }

        private IEnumerator CreateAndPopulateSpears()
        {
            for (int i = 0; i < storedData.spearData.Count; i++)
            {
                StoredData.SpearData spearData = storedData.spearData[i];

                BaseEntity spear = CreateWorldObject(spearData.itemId, string.Empty, spearData.Position, true);  
                spear.GetComponent<Rigidbody>().isKinematic = true;
                spear.transform.rotation = Quaternion.Euler(spearData.Rotation);

                List<DroppedItem> skulls = Pool.GetList<DroppedItem>();

                for (int y = 0; y < spearData.trophyData.Count; y++)
                {
                    StoredData.TrophyData data = spearData.trophyData[y];

                    DroppedItem skullItem = CreateSkullItem(data.displayName, spear, data.Position, data.Rotation);

                    skulls.Add(skullItem);
                }

                spearRegisteredSkulls.Add(spear as DroppedItem, skulls);

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

        private void InitializeSign(Signage sign, string name, Vector3 localPosition, Vector3 localRotation)
        {              
            BaseEntity[] children = sign.children.Where(x => x.GetComponent<DroppedItem>())?.ToArray() ?? null;

            if (children != null)
            {
                for (int i = 0; i < children.Length; i++)
                {
                    sign.RemoveChild(children[i]);
                    children[i].Kill();
                }
            }
          
            DroppedItem skullItem = CreateSkullItem(name, sign, localPosition, localRotation);

            UpdateSignImage(sign, name);

            signRegisteredSkulls.Add(sign, skullItem);
        }

        private void InitializeSpear(DroppedItem spear, string name, Vector3 localPosition, Vector3 localRotation)
        {      
            spear.CancelInvoke(spear.IdleDestroy);

            DroppedItem droppedItem = CreateSkullItem(name, spear, localPosition, localRotation);

            List<DroppedItem> skulls;
            if (!spearRegisteredSkulls.TryGetValue(spear, out skulls))
                skulls = spearRegisteredSkulls[spear] = Pool.GetList<DroppedItem>();

            skulls.Add(droppedItem);
        }
        #endregion

        #region Entity Creation
        private DroppedItem CreateSkullItem(string name, BaseEntity parent, Vector3 localPosition, Vector3 localRotation, bool canPickup = true)
        {
            DroppedItem skullItem = CreateSkullItem(name, parent.transform.position);

            skullItem.SetParent(parent);
            skullItem.transform.localPosition = localPosition;
            skullItem.transform.rotation = Quaternion.Euler(localRotation);

            return skullItem;
        }

        private DroppedItem CreateSkullItem(string name, Vector3 position, bool canPickup = true)
        {
            BaseEntity skullEntity = CreateWorldObject(SKULL_ITEM_ID, name, position, canPickup);

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

            return skullEntity as DroppedItem;
        }

        private BaseEntity CreateWorldObject(int itemId, string name, Vector3 pos, bool canPickup)
        {
            Item item = ItemManager.CreateByItemID(itemId);

            if (!string.IsNullOrEmpty(name))
                item.name = name;

            BaseEntity worldEntity = GameManager.server.CreateEntity(BURLAPSACK_PREFAB, pos);

            WorldItem worldItem = worldEntity as WorldItem;
            if (worldItem != null)
                worldItem.InitializeItem(item);

            worldEntity.Invoke(() =>
            {
                (worldEntity as DroppedItem).CancelInvoke((worldEntity as DroppedItem).IdleDestroy);                      
            }, 1f);
            
            worldItem.enableSaving = false;
            worldItem.allowPickup = canPickup;
            worldEntity.Spawn();

            item.SetWorldEntity(worldEntity);

            return worldEntity;
        }
        #endregion

        #region Functions

        private bool CanRemove(BasePlayer player, string key)
        {
            if (!configData.Placement.RemoveSkulls)
                return false;

            if (configData.Placement.RequirePrivilegeRemove && !player.IsBuildingAuthed())
            {
                SendReply(player, msg(key, player.userID));
                return false;
            }

            return true;
        }

        private static bool CanPlace(BasePlayer player)
        {
            if (configData.Placement.RequirePrivilegePlace && !player.IsBuildingAuthed())
                return false;

            return true;
        }
        #endregion

        #region Image Storage
        private void UpdateSignImage(Signage signage, string text, bool hideText = false)
        {
            if (!configData.Sign.GenerateImage)
                return;
            
            imageStorage.AddQueueItem(new ImageStorage.QueueItem(text, signage, hideText));            
        }        

        private class ImageStorage : MonoBehaviour
        {
            private Queue<QueueItem> queue;
            private WWW www;
            private QueueItem queueItem;
            private bool isBusy;

            private string backgroundColor;
            private string textColor;
            private int textSize;

            private void Awake()
            {
                queue = new Queue<QueueItem>();
                backgroundColor = configData.Sign.BackgroundColor;
                textColor = configData.Sign.TextColor;
                textSize = configData.Sign.TextSize;
            }

            private void OnDestroy()
            {
                www.Dispose();
                queue.Clear();
                Destroy(gameObject);
            }

            public void AddQueueItem(QueueItem queueItem)
            {
                queue.Enqueue(queueItem);
                if (!isBusy)
                    StartNextItem();
            }

            private void StartNextItem()
            {
                isBusy = true;

                queueItem = queue.Dequeue();

                if (queueItem.signage == null || queueItem.signage.IsDestroyed)
                {
                    isBusy = false;
                    StartNextItem();
                    return;
                }

                StartCoroutine(DownloadImage());
            }
            
            private IEnumerator DownloadImage()
            {
                ImageSize imageSize;
                if (!ImageSize.Sizes.TryGetValue(queueItem.signage.ShortPrefabName, out imageSize))
                {
                    print($"[ERROR] TrophySigns: No sign sizes set for {queueItem.signage.ShortPrefabName}, please report this in the plugin support thread");

                    isBusy = false;
                    if (queue.Count > 0)
                        StartNextItem();
                    yield break;
                }

                float scale = (float)imageSize.Width / (float)600;

                int targetFontSize = (int)(textSize * scale);

                string imageUrl = $"https://dummyimage.com/{imageSize.Width}x{imageSize.Height}/{backgroundColor}/{(queueItem.hideText ? backgroundColor : textColor)}.png/&text={queueItem.text.Replace(" ", "+")}";

                www = new WWW(imageUrl);

                yield return new WaitWhile(() => !www.isDone);

                byte[] imageBytes = www.texture.EncodeToPNG();

                if (imageSize.Width != imageSize.ImageWidth || imageSize.Height != imageSize.ImageHeight)
                    imageBytes = ResizeImage(imageBytes, imageSize);

                queueItem.signage.textureID = FileStorage.server.Store(imageBytes, FileStorage.Type.png, queueItem.signage.net.ID, 0U);
                queueItem.signage.SendNetworkUpdate(BasePlayer.NetworkQueue.Update);

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

                isBusy = false;
                www.Dispose();

                if (queue.Count > 0)
                    StartNextItem();
            }

            private byte[] ResizeImage(byte[] bytes, ImageSize imageSize)
            {
                byte[] resizedImageBytes;
                using (MemoryStream originalBytesStream = new MemoryStream(), resizedBytesStream = new MemoryStream())
                {
                    originalBytesStream.Write(bytes, 0, bytes.Length);
                    Bitmap image = new Bitmap(originalBytesStream);

                    Bitmap resizedImage = new Bitmap(imageSize.Width, imageSize.Height);

                    using (System.Drawing.Graphics graphics = System.Drawing.Graphics.FromImage(resizedImage))
                    {
                        graphics.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceCopy;
                        graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
                        graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
                        graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                        graphics.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;

                        graphics.DrawImage(image, new Rectangle(0, 0, imageSize.ImageWidth, imageSize.ImageHeight));
                    }

                    resizedImage.Save(resizedBytesStream, ImageFormat.Png);
                    resizedImageBytes = resizedBytesStream.ToArray();
                }
                return resizedImageBytes;
            }

            public class QueueItem
            {
                public string text;
                public bool hideText;
                public Signage signage;

                public QueueItem() { }
                public QueueItem(string text, Signage signage, bool hideText)
                {
                    this.text = text;
                    this.signage = signage;
                    this.hideText = hideText;
                }
            }                       

            private class ImageSize
            {
                public int Width { get; }
                public int Height { get; }
                public int ImageWidth { get; }
                public int ImageHeight { get; }

                public ImageSize(int width, int height) : this(width, height, width, height) { }
                public ImageSize(int width, int height, int imageWidth, int imageHeight)
                {
                    Width = width;
                    Height = height;
                    ImageWidth = imageWidth;
                    ImageHeight = imageHeight;
                }

                public static Dictionary<string, ImageSize> Sizes = new Dictionary<string, ImageSize>
                {
                    ["sign.pictureframe.landscape"] = new ImageSize(256, 128),
                    ["sign.pictureframe.tall"] = new ImageSize(128, 512),
                    ["sign.pictureframe.portrait"] = new ImageSize(128, 256),
                    ["sign.pictureframe.xxl"] = new ImageSize(1024, 512),
                    ["sign.pictureframe.xl"] = new ImageSize(512, 512),
                    ["sign.small.wood"] = new ImageSize(128, 64),
                    ["sign.huge.wood"] = new ImageSize(512, 128),
                    ["sign.medium.wood"] = new ImageSize(256, 128),
                    ["sign.large.wood"] = new ImageSize(256, 128),
                    ["sign.hanging.banner.large"] = new ImageSize(64, 256),
                    ["sign.pole.banner.large"] = new ImageSize(64, 256),
                    ["sign.post.single"] = new ImageSize(128, 64),
                    ["sign.post.double"] = new ImageSize(256, 256),
                    ["sign.post.town"] = new ImageSize(256, 128),
                    ["sign.post.town.roof"] = new ImageSize(256, 128),
                    ["sign.hanging"] = new ImageSize(128, 256),
                    ["sign.hanging.ornate"] = new ImageSize(256, 128),
                    ["spinner.wheel.deployed"] = new ImageSize(512, 512, 285, 285),
                };
            }
        }
        #endregion

        #region Component
        private class ItemPlacement : MonoBehaviour
        {
            private BasePlayer player;

            private DroppedItem skullItem;

            private BaseEntity hitEntity = null;

            private bool isValidPlacement;

            private float placementDistance = 3f;

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

                SpawnDroppedItem(player.GetActiveItem()?.name);
                player.ChatMessage(msg("Help.Placement.1", player.userID));
            }

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

                isValidPlacement = false;

                InputState input = player.serverInput;

                RaycastHit hit;
                if (Physics.Raycast(player.eyes.HeadRay(), out hit, placementDistance, TARGET_LAYERS))
                {
                    skullItem.transform.position = hit.point + (-skullItem.transform.up * 0.1f);
                    skullItem.transform.rotation = Quaternion.LookRotation(player.eyes.position - skullItem.transform.position, Vector3.up) * Quaternion.Euler(270, 0, 0);

                    hitEntity = hit.GetEntity();

                    isValidPlacement = hitEntity is Signage || ((hitEntity is DroppedItem) && (hitEntity as DroppedItem).item.info.shortname.Contains("spear."));
                }
                else
                {
                    skullItem.transform.position = player.eyes.HeadRay().GetPoint(2);
                    skullItem.transform.rotation = Quaternion.LookRotation(player.eyes.position - skullItem.transform.position, Vector3.up) * Quaternion.Euler(270, 0, 0);
                }

                if (input.WasJustPressed(BUTTON.FIRE_PRIMARY))
                {
                    if (!isValidPlacement)
                    {
                        player.ChatMessage(msg("Help.Placement.2", player.userID));
                        return;
                    }
                    else
                    {
                        if (hitEntity is Signage)
                        {
                            if (Instance.signRegisteredSkulls.ContainsKey(hitEntity as Signage))
                                player.ChatMessage(msg("Help.Placement.5", player.userID));
                            else PlaceSkull(activeItem);
                        }
                        else if (hitEntity is DroppedItem)
                        {
                            if (hitEntity.GetComponent<Rigidbody>()?.isKinematic ?? false)
                                PlaceSkull(activeItem);
                        }
                    }
                }
                else if (input.WasJustPressed(BUTTON.FIRE_SECONDARY))
                    CancelPlacement();
            }

            private void SpawnDroppedItem(string name)
            {
                skullItem = Instance.CreateSkullItem(name, player.transform.position, false);
                skullItem.item.GetWorldEntity().gameObject.SetLayerRecursive(28);
                enabled = true;
            }

            public void CancelPlacement(bool notify = true)
            {
                enabled = false;
                skullItem.DestroyItem();
                skullItem.Kill();
                if (notify)
                    player.ChatMessage(msg("Help.Placement.3", player.userID));
                Destroy(this);
            }

            private void PlaceSkull(Item activeItem)
            {
                if (!CanPlace(player))
                {
                    player.ChatMessage(msg("Error.NoBuildingAuthPlacement", player.userID));
                    CancelPlacement(false);
                    return;
                }

                player.ChatMessage(msg("Help.Placement.4", player.userID));

                activeItem.MarkDirty();
                activeItem.RemoveFromContainer();

                string name = string.IsNullOrEmpty(skullItem.item.name) ? player.displayName : skullItem.item.name.Replace("Skull of ", "").Replace("\"", "");
                name = string.Format(configData.Sign.SignFormat, name);

                if (hitEntity is Signage)                
                    Instance.InitializeSign(hitEntity as Signage, name, hitEntity.transform.InverseTransformPoint(skullItem.transform.position), skullItem.transform.eulerAngles);                
                else Instance.InitializeSpear(hitEntity as DroppedItem, name, hitEntity.transform.InverseTransformPoint(skullItem.transform.position), skullItem.transform.eulerAngles);

                skullItem.DestroyItem();
                skullItem.Kill();

                Destroy(this);
            }

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

        #region Config        
        private static ConfigData configData;

        public class ConfigData
        {
            [JsonProperty(PropertyName = "Placement Options")]
            public PlacementOptions Placement { get; set; }

            [JsonProperty(PropertyName = "Sign Options")]
            public SignOptions Sign { get; set; }

            public class SignOptions
            {
                [JsonProperty(PropertyName = "Auto-generate sign image using skull owner")]
                public bool GenerateImage { get; set; }

                [JsonProperty(PropertyName = "Image background color (hex without the #)")]
                public string BackgroundColor { get; set; }

                [JsonProperty(PropertyName = "Text color (hex without the #)")]
                public string TextColor { get; set; }

                [JsonProperty(PropertyName = "Sign text format")]
                public string SignFormat { get; set; }

                [JsonProperty(PropertyName = "Text size")]
                public int TextSize { get; set; }
            }

            public class PlacementOptions
            {
                [JsonProperty(PropertyName = "Allow skulls and spears to be removed")]
                public bool RemoveSkulls { get; set; }

                [JsonProperty(PropertyName = "Require building privilege to remove skulls and spears")]
                public bool RequirePrivilegeRemove { get; set; }

                [JsonProperty(PropertyName = "Require building privilege to place skulls and spears")]
                public bool RequirePrivilegePlace { 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
            {
                Placement = new ConfigData.PlacementOptions
                {
                    RemoveSkulls = true,
                    RequirePrivilegePlace = true,
                    RequirePrivilegeRemove = true,
                },
                Sign = new ConfigData.SignOptions
                {
                    BackgroundColor = "282828",
                    GenerateImage = true,
                    TextColor = "cccccc",
                    TextSize = 60,
                    SignFormat = "Skull of \"{0}\""
                },
                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.Sign.TextSize = baseConfig.Sign.TextSize;

            if (configData.Version < new VersionNumber(0, 1, 10))
                configData.Sign.SignFormat = baseConfig.Sign.SignFormat;

            if (configData.Version < new VersionNumber(0, 2, 0))
                configData = baseConfig;

            configData.Version = Version;
            PrintWarning("Config update completed!");
        }

        #endregion

        #region Data Management
        private void SaveData()
        {
            storedData.data.Clear();
            storedData.spearData.Clear();

            foreach (KeyValuePair<Signage, DroppedItem> kvp in signRegisteredSkulls)
            {
                if (kvp.Key == null || kvp.Key.IsDestroyed || kvp.Value == null || kvp.Value.IsDestroyed)
                    continue;

                storedData.data.Add(kvp.Key.net.ID, new StoredData.TrophyData(kvp.Value));
            }

            foreach (KeyValuePair<DroppedItem, List<DroppedItem>> kvp in spearRegisteredSkulls)
            {
                if (kvp.Key == null || kvp.Key.IsDestroyed || kvp.Value == null || kvp.Value.Count == 0)
                    continue;

                storedData.spearData.Add(new StoredData.SpearData(kvp.Key, kvp.Value.Select(x => new StoredData.TrophyData(x)).ToList()));
            }

            data.WriteObject(storedData);
        }

        private void LoadData()
        {
            try
            {
                storedData = data.ReadObject<StoredData>();
            }
            catch
            {
                storedData = new StoredData();
            }
        }

        private class StoredData
        {
            public Dictionary<uint, TrophyData> data = new Dictionary<uint, TrophyData>();

            public List<SpearData> spearData = new List<SpearData>();

            public class SpearData : PositionData
            {               
                public int itemId;

                public List<TrophyData> trophyData;

                public SpearData() { }

                public SpearData(DroppedItem item, List<TrophyData> trophyData) : base(item)
                {                   
                    itemId = item.item.info.itemid;
                    this.trophyData = trophyData;
                }
            }

            public class TrophyData : PositionData
            {                
                public string displayName;

                public TrophyData() { }

                public TrophyData(DroppedItem item) : base(item)
                {                   
                    displayName = item.item.name;
                }
            }

            public class PositionData
            {
                public float[] position;
                public float[] rotation;

                public PositionData() { }

                public PositionData(DroppedItem item)
                {
                    position = new float[] { item.transform.localPosition.x, item.transform.localPosition.y, item.transform.localPosition.z };
                    rotation = new float[] { item.transform.eulerAngles.x, item.transform.eulerAngles.y, item.transform.eulerAngles.z };
                }

                [JsonIgnore]
                public Vector3 Position
                {
                    get
                    {
                        return new Vector3(position[0], position[1], position[2]);
                    }
                }

                [JsonIgnore]
                public Vector3 Rotation
                {
                    get
                    {
                        return new Vector3(rotation[0], rotation[1], rotation[2]);
                    }
                }
            }
        }
        #endregion

        #region Localization
        private static string msg(string key, ulong playerId = 0U) => Instance.lang.GetMessage(key, Instance, playerId == 0U ? null : playerId.ToString());

        private Dictionary<string, string> Messages = new Dictionary<string, string>
        {            
            ["Help.Placement.1"] = "<color=#939393>Use the <color=#ce422b>fire</color> button to place this skull on any sign or spear</color>",
            ["Help.Placement.2"] = "<color=#939393>Skulls can only be placed on signs or spears</color>",
            ["Help.Placement.3"] = "<color=#ce422b>Skull placement cancelled!</color>",
            ["Help.Placement.4"] = "<color=#ce422b>Skull placed!</color>",
            ["Help.Placement.5"] = "<color=#939393>This sign already has a skull on it!</color>",
            ["Error.NoBuildingAuthSkull"] = "<color=#939393>You need building auth to remove skulls</color>",
            ["Error.NoBuildingAuthSpear"] = "<color=#939393>You need building auth to remove spears</color>",
            ["Error.SkullsOnSpear"] = "<color=#939393>You need to remove the skulls before you can remove the spear</color>",
            ["Error.NoBuildingAuthPlacement"] = "<color=#939393>You need building auth to place skulls</color>",
        };
        #endregion
    }
}

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