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

FREE CopyPaste : 4.1.36 4.1.36

Нет прав для скачивания
C#:
//If debug is defined it will add a stopwatch to the paste and copydata which can be used to profile copying and pasting.// #define DEBUG

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using Facepunch;
using Newtonsoft.Json;
using Oxide.Core;
using Oxide.Core.Libraries.Covalence;
using Oxide.Game.Rust.Libraries.Covalence;
using ProtoBuf;
using UnityEngine;
using Graphics = System.Drawing.Graphics;

// ReSharper disable SpecifyACultureInStringConversionExplicitly

/*
 * CREDITS
 *
 * Orange - Saving ContainerIOEntity
 * UIP88 - Turrets fix
 * bsdinis - Wire fix
 * nivex - Ownership option, sign fix
 * DezLife - CCTV fix
 * Wulf - Skipping 4.1.24 :D
 * 
 */

namespace Oxide.Plugins
{
    [Info("Copy Paste", "misticos", "4.1.36")]
    [Description("Copy and paste buildings to save them or move them")]
    public class CopyPaste : CovalencePlugin
    {
        // ReSharper disable once Unity.IncorrectMonoBehaviourInstantiation
        private readonly Item _emptyItem = new Item { info = new ItemDefinition() };
        private readonly IPlayer _consolePlayer = new RustConsolePlayer();

        private int _copyLayer =
                LayerMask.GetMask("Construction", "Prevent Building", "Construction Trigger", "Trigger", "Deployed",
                    "Default", "Ragdoll"),
            _groundLayer = LayerMask.GetMask("Terrain", "Default"),
            _rayCopy = LayerMask.GetMask("Construction", "Deployed", "Tree", "Resource", "Prevent Building"),
            _rayPaste = LayerMask.GetMask("Construction", "Deployed", "Tree", "Terrain", "World", "Water",
                "Prevent Building");

        private string _copyPermission = "copypaste.copy",
            _listPermission = "copypaste.list",
            _pastePermission = "copypaste.paste",
            _pastebackPermission = "copypaste.pasteback",
            _undoPermission = "copypaste.undo",
            _subDirectory = "copypaste/";

        private Dictionary<string, Stack<List<BaseEntity>>> _lastPastes =
            new Dictionary<string, Stack<List<BaseEntity>>>();

        private Dictionary<string, SignSize> _signSizes = new Dictionary<string, SignSize>
        {
            //{"spinner.wheel.deployed", new SignSize(512, 512)},
            { "sign.pictureframe.landscape", new SignSize(256, 128) },
            { "sign.pictureframe.tall", new SignSize(128, 512) },
            { "sign.pictureframe.portrait", new SignSize(128, 256) },
            { "sign.pictureframe.xxl", new SignSize(1024, 512) },
            { "sign.pictureframe.xl", new SignSize(512, 512) },
            { "sign.small.wood", new SignSize(128, 64) },
            { "sign.medium.wood", new SignSize(256, 128) },
            { "sign.large.wood", new SignSize(256, 128) },
            { "sign.huge.wood", new SignSize(512, 128) },
            { "sign.hanging.banner.large", new SignSize(64, 256) },
            { "sign.pole.banner.large", new SignSize(64, 256) },
            { "sign.post.single", new SignSize(128, 64) },
            { "sign.post.double", new SignSize(256, 256) },
            { "sign.post.town", new SignSize(256, 128) },
            { "sign.post.town.roof", new SignSize(256, 128) },
            { "sign.hanging", new SignSize(128, 256) },
            { "sign.hanging.ornate", new SignSize(256, 128) },
            { "sign.neon.xl.animated", new SignSize(250, 250) },
            { "sign.neon.xl", new SignSize(250, 250) },
            { "sign.neon.125x215.animated", new SignSize(215, 125) },
            { "sign.neon.125x215", new SignSize(215, 125) },
            { "sign.neon.125x125", new SignSize(125, 125) },
        };

        private List<BaseEntity.Slot> _checkSlots = new List<BaseEntity.Slot>
        {
            BaseEntity.Slot.Lock,
            BaseEntity.Slot.UpperModifier,
            BaseEntity.Slot.MiddleModifier,
            BaseEntity.Slot.LowerModifier
        };

        public enum CopyMechanics
        {
            Building,
            Proximity
        }

        private class SignSize
        {
            public int Width;
            public int Height;

            public SignSize(int width, int height)
            {
                Width = width;
                Height = height;
            }
        }

        //Config

        private ConfigData _config;

        private class ConfigData
        {
            [JsonProperty(PropertyName = "Copy Options")]
            public CopyOptions Copy { get; set; }

            [JsonProperty(PropertyName = "Paste Options")]
            public PasteOptions Paste { get; set; }

            [JsonProperty(PropertyName =
                "Amount of entities to paste per batch.Use to tweak performance impact of pasting")]
            [DefaultValue(15)]
            public int PasteBatchSize = 15;

            [JsonProperty(PropertyName =
                "Amount of entities to copy per batch.Use to tweak performance impact of copying")]
            [DefaultValue(100)]
            public int CopyBatchSize = 100;

            [JsonProperty(PropertyName =
                "Amount of entities to undo per batch.Use to tweak performance impact of undoing")]
            [DefaultValue(15)]
            public int UndoBatchSize = 15;

            [JsonProperty(PropertyName = "Enable data saving feature")]
            [DefaultValue(true)]
            public bool DataSaving = true;

            public class CopyOptions
            {
                [JsonProperty(PropertyName = "Check radius from each entity (true/false)")]
                [DefaultValue(true)]
                public bool EachToEach { get; set; } = true;

                [JsonProperty(PropertyName = "Share (true/false)")]
                [DefaultValue(false)]
                public bool Share { get; set; } = false;

                [JsonProperty(PropertyName = "Tree (true/false)")]
                [DefaultValue(false)]
                public bool Tree { get; set; } = false;

                [JsonProperty(PropertyName = "Default radius to look for entities from block")]
                [DefaultValue(3.0f)]
                public float Radius { get; set; } = 3.0f;
            }

            public class PasteOptions
            {
                [JsonProperty(PropertyName = "Auth (true/false)")]
                [DefaultValue(false)]
                public bool Auth { get; set; } = false;

                [JsonProperty(PropertyName = "Deployables (true/false)")]
                [DefaultValue(true)]
                public bool Deployables { get; set; } = true;

                [JsonProperty(PropertyName = "Inventories (true/false)")]
                [DefaultValue(true)]
                public bool Inventories { get; set; } = true;

                [JsonProperty(PropertyName = "Vending Machines (true/false)")]
                [DefaultValue(true)]
                public bool VendingMachines { get; set; } = true;

                [JsonProperty(PropertyName = "Stability (true/false)")]
                [DefaultValue(true)]
                public bool Stability { get; set; } = true;

                [JsonProperty(PropertyName = "EntityOwner (true/false)")]
                [DefaultValue(true)]
                public bool EntityOwner { get; set; } = true;
            }
        }

        private void LoadVariables()
        {
            Config.Settings.DefaultValueHandling = DefaultValueHandling.Populate;

            _config = Config.ReadObject<ConfigData>();

            Config.WriteObject(_config, true);
        }

        protected override void LoadDefaultConfig()
        {
            var configData = new ConfigData
            {
                Copy = new ConfigData.CopyOptions(),
                Paste = new ConfigData.PasteOptions()
            };

            Config.WriteObject(configData, true);
        }

        //Hooks

        private void Init()
        {
            permission.RegisterPermission(_copyPermission, this);
            permission.RegisterPermission(_listPermission, this);
            permission.RegisterPermission(_pastePermission, this);
            permission.RegisterPermission(_pastebackPermission, this);
            permission.RegisterPermission(_undoPermission, this);

            var compiledLangs = new Dictionary<string, Dictionary<string, string>>();

            foreach (var line in _messages)
            {
                foreach (var translate in line.Value)
                {
                    if (!compiledLangs.ContainsKey(translate.Key))
                        compiledLangs[translate.Key] = new Dictionary<string, string>();

                    compiledLangs[translate.Key][line.Key] = translate.Value;
                }
            }

            foreach (var cLangs in compiledLangs)
            {
                lang.RegisterMessages(cLangs.Value, this, cLangs.Key);
            }
        }

        private void OnServerInitialized()
        {
            LoadVariables();

            Vis.colBuffer = new Collider[8192 * 16];

            JsonConvert.DefaultSettings = () => new JsonSerializerSettings
            {
                Formatting = Formatting.Indented,
                ReferenceLoopHandling = ReferenceLoopHandling.Ignore
            };
        }

        #region API

        private object TryCopyFromSteamId(ulong userId, string filename, string[] args, Action callback = null)
        {
            var player = players.FindPlayerById(userId.ToString())?.Object as BasePlayer;
            if (player == null)
                return Lang("NOT_FOUND_PLAYER");

            RaycastHit hit;

            if (!Physics.Raycast(player.eyes.HeadRay(), out hit, 1000f, _rayCopy))
                return Lang("NO_ENTITY_RAY", player.UserIDString);

            return TryCopy(hit.point, hit.GetEntity().GetNetworkRotation().eulerAngles, filename,
                DegreeToRadian(player.GetNetworkRotation().eulerAngles.y), args, player.IPlayer, callback);
        }

        private object TryPasteFromSteamId(ulong userId, string filename, string[] args, Action callback = null,
            Action<BaseEntity> callbackSpawned = null)
        {
            var player = players.FindPlayerById(userId.ToString())?.Object as BasePlayer;
            if (player == null)
                return Lang("NOT_FOUND_PLAYER");

            RaycastHit hit;

            if (!Physics.Raycast(player.eyes.HeadRay(), out hit, 1000f, _rayPaste))
                return Lang("NO_ENTITY_RAY", player.UserIDString);

            return TryPaste(hit.point, filename, player.IPlayer,
                DegreeToRadian(player.GetNetworkRotation().eulerAngles.y),
                args, callback: callback, callbackSpawned: callbackSpawned).Item1;
        }

        private object TryPasteFromVector3(Vector3 pos, float rotationCorrection, string filename, string[] args,
            Action callback = null, Action<BaseEntity> callbackSpawned = null)
        {
            return TryPaste(pos, filename, _consolePlayer, rotationCorrection, args, callback: callback,
                callbackSpawned: callbackSpawned).Item1;
        }

        private ValueTuple<object, Action> TryPasteFromVector3Cancellable(Vector3 pos, float rotationCorrection,
            string filename, string[] args,
            Action callback = null, Action<BaseEntity> callbackSpawned = null)
        {
            var result = TryPaste(pos, filename, _consolePlayer, rotationCorrection, args, callback: callback,
                callbackSpawned: callbackSpawned);

            var pasteData = result.Item2;

            return new ValueTuple<object, Action>(result.Item1, () => pasteData.Cancelled = true);
        }

        #endregion

        //Other methods

        private object CheckCollision(HashSet<Dictionary<string, object>> entities, Vector3 startPos, float radius)
        {
            foreach (var entityobj in entities)
            {
                if (Physics.CheckSphere((Vector3)entityobj["position"], radius, _copyLayer))
                    return Lang("BLOCKING_PASTE");
            }

            return true;
        }

        private bool CheckPlaced(string prefabname, Vector3 pos, Quaternion rot)
        {
            const float maxDiff = 0.01f;

            var ents = Pool.GetList<BaseEntity>();
            try
            {
                Vis.Entities(pos, maxDiff, ents);

                foreach (var ent in ents)
                {
                    if (ent.PrefabName != prefabname)
                        continue;

                    if (Vector3.Distance(ent.transform.position, pos) > maxDiff)
                    {
                        continue;
                    }

                    if (Vector3.Distance(ent.transform.rotation.eulerAngles, rot.eulerAngles) > maxDiff)
                    {
                        continue;
                    }

                    return true;
                }

                return false;
            }
            finally
            {
                Pool.FreeList(ref ents);
            }
        }

        private void UndoLoop(HashSet<BaseEntity> entities, IPlayer player, int count = 0)
        {
            foreach (var storageContainer in entities.OfType<StorageContainer>().Where(x => !x.IsDestroyed))
            {
                storageContainer.Kill();
            }

            // Take an amount of entities from the entity list (defined in config) and kill them.Will be repeated for every tick until there are no entities left.entities.Take(_config.UndoBatchSize).ToList().ForEach(p =>
                {
                    entities.Remove(p);

                    // Cleanup the hotspot beloning to the node.var ore = p as OreResourceEntity;
                    if (ore != null)
                    {
                        ore.CleanupBonus();
                    }

                    var io = p as IOEntity;
                    if (io != null)
                    {
                        io.ClearConnections();
                    }

                    if (p != null && !p.IsDestroyed)
                        p.Kill();
                });

            // If it gets stuck in infinite loop break the loop.if (count != 0 && entities.Count != 0 && entities.Count == count)
            {
                player?.Reply("Undo cancelled because of infinite loop.");
                return;
            }

            if (entities.Count > 0)
                NextTick(() => UndoLoop(entities, player, entities.Count));
            else if (player != null)
            {
                player.Reply(Lang("UNDO_SUCCESS", player.Id));

                if (_lastPastes.ContainsKey(player.Id) && _lastPastes[player.Id].Count == 0)
                    _lastPastes.Remove(player.Id);
            }
        }

        private void Copy(Vector3 sourcePos, Vector3 sourceRot, string filename, float rotationCorrection,
            CopyMechanics copyMechanics, float range, bool saveTree, bool saveShare, bool eachToEach, IPlayer player,
            Action callback)
        {
            var currentLayer = _copyLayer;

            if (saveTree)
                currentLayer |= LayerMask.GetMask("Tree");

            var copyData = new CopyData
            {
                Filename = filename,
                CurrentLayer = currentLayer,
                RotCor = rotationCorrection,
                Range = range,
                SaveShare = saveShare,
                SaveTree = saveTree,
                CopyMechanics = copyMechanics,
                EachToEach = eachToEach,
                SourcePos = sourcePos,
                SourceRot = sourceRot,
                Player = player,
                BasePlayer = player.Object as BasePlayer,
                Callback = callback
            };

            copyData.CheckFrom.Push(sourcePos);

            NextTick(() => CopyLoop(copyData));
        }

        // Main loop for copy, will fetch all the data needed.Is called every tick untill copy is done (can't find any entities)
        private void CopyLoop(CopyData copyData)
        {
            var checkFrom = copyData.CheckFrom;
            var houseList = copyData.HouseList;
            var buildingId = copyData.BuildingId;
            var copyMechanics = copyData.CopyMechanics;
            var batchSize = checkFrom.Count < _config.CopyBatchSize ? checkFrom.Count : _config.CopyBatchSize;

            for (var i = 0; i < batchSize; i++)
            {
                if (checkFrom.Count == 0)
                    break;

                var list = Pool.GetList<BaseEntity>();
                try
                {
                    Vis.Entities(checkFrom.Pop(), copyData.Range, list, copyData.CurrentLayer);

                    foreach (var entity in list)
                    {
                        if (!houseList.Add(entity))
                            continue;

                        if (copyMechanics == CopyMechanics.Building)
                        {
                            var buildingBlock = entity.GetComponentInParent<BuildingBlock>();

                            if (buildingBlock != null)
                            {
                                if (buildingId == 0)
                                    buildingId = buildingBlock.buildingID;

                                if (buildingId != buildingBlock.buildingID)
                                    continue;
                            }
                        }

                        var transform = entity.transform;
                        if (copyData.EachToEach)
                            checkFrom.Push(transform.position);

                        if (entity.GetComponent<BaseLock>() != null)
                            continue;

                        copyData.RawData.Add(EntityData(entity, transform.position,
                            transform.rotation.eulerAngles / 57.29578f, copyData));
                    }
                }
                finally
                {
                    Pool.FreeList(ref list);
                }

                copyData.BuildingId = buildingId;
            }

            if (checkFrom.Count > 0)
            {
                NextTick(() => CopyLoop(copyData));
            }
            else
            {
                var path = _subDirectory + copyData.Filename;
                var datafile = Interface.Oxide.DataFileSystem.GetDatafile(path);

                datafile.Clear();

                var sourcePos = copyData.SourcePos;

                datafile["default"] = new Dictionary<string, object>
                {
                    {
                        "position", new Dictionary<string, object>
                        {
                            { "x", sourcePos.x.ToString() },
                            { "y", sourcePos.y.ToString() },
                            { "z", sourcePos.z.ToString() }
                        }
                    },
                    { "rotationy", copyData.SourceRot.y.ToString() },
                    { "rotationdiff", copyData.RotCor.ToString() }
                };

                datafile["entities"] = copyData.RawData;
                datafile["protocol"] = new Dictionary<string, object>
                {
                    { "items", 2 },
                    { "version", Version }
                };

                Interface.Oxide.DataFileSystem.SaveDatafile(path);

                copyData.Player.Reply(Lang("COPY_SUCCESS", copyData.Player.Id, copyData.Filename));

                copyData.Callback?.Invoke();

                Interface.CallHook("OnCopyFinished", copyData.RawData, copyData.Filename, copyData.Player, copyData.SourcePos);
            }
        }

        private float DegreeToRadian(float angle)
        {
            return (float)(Math.PI * angle / 180.0f);
        }

        private Dictionary<string, object> EntityData(BaseEntity entity, Vector3 entPos, Vector3 entRot,
            CopyData copyData)
        {
            var normalizedPos = NormalizePosition(copyData.SourcePos, entPos, copyData.RotCor);

            entRot.y -= copyData.RotCor;

            var data = new Dictionary<string, object>
            {
                { "prefabname", entity.PrefabName },
                { "skinid", entity.skinID },
                { "flags", TryCopyFlags(entity) },
                {
                    "pos", new Dictionary<string, object>
                    {
                        { "x", normalizedPos.x.ToString() },
                        { "y", normalizedPos.y.ToString() },
                        { "z", normalizedPos.z.ToString() }
                    }
                },
                {
                    "rot", new Dictionary<string, object>
                    {
                        { "x", entRot.x.ToString() },
                        { "y", entRot.y.ToString() },
                        { "z", entRot.z.ToString() }
                    }
                },
                { "ownerid", entity.OwnerID }
            };

            var growableEntity = entity as GrowableEntity;
            if (growableEntity != null)
            {
                var genes = GrowableGeneEncoding.EncodeGenesToInt(growableEntity.Genes);
                if (genes > 0)
                {
                    data.Add("genes", genes);
                }

                var perent = growableEntity.GetParentEntity();
                if (perent != null)
                {
                    data.Add("hasParent", true);
                }
            }

            TryCopySlots(entity, data, copyData.SaveShare);

            var buildingblock = entity as BuildingBlock;

            if (buildingblock != null)
            {
                data.Add("grade", buildingblock.grade);
            }

            var box = entity as StorageContainer;
            if (box?.inventory != null)
            {
                var itemlist = new List<object>();

                foreach (var item in box.inventory.itemList)
                {
                    var itemdata = new Dictionary<string, object>
                    {
                        { "condition", item.condition.ToString() },
                        { "id", item.info.itemid },
                        { "amount", item.amount },
                        { "skinid", item.skin },
                        { "position", item.position },
                        { "blueprintTarget", item.blueprintTarget },
                        { "dataInt", item.instanceData?.dataInt ?? 0 }
                    };

                    if (!string.IsNullOrEmpty(item.text))
                        itemdata["text"] = item.text;

                    var heldEnt = item.GetHeldEntity();

                    if (heldEnt != null)
                    {
                        var projectiles = heldEnt.GetComponent<BaseProjectile>();

                        if (projectiles != null)
                        {
                            var magazine = projectiles.primaryMagazine;

                            if (magazine != null)
                            {
                                itemdata.Add("magazine", new Dictionary<string, object>
                                {
                                    { magazine.ammoType.itemid.ToString(), magazine.contents }
                                });
                            }
                        }
                    }

                    if (item?.contents?.itemList != null)
                    {
                        var contents = new List<object>();

                        foreach (var itemContains in item.contents.itemList)
                        {
                            contents.Add(new Dictionary<string, object>
                            {
                                { "id", itemContains.info.itemid },
                                { "amount", itemContains.amount }
                            });
                        }

                        itemdata["items"] = contents;
                    }

                    itemlist.Add(itemdata);
                }

                data.Add("items", itemlist);
            }

            var box2 = entity as ContainerIOEntity;
            if (box2 != null)
            {
                var itemlist = new List<object>();

                foreach (var item in box2.inventory.itemList)
                {
                    var itemdata = new Dictionary<string, object>
                    {
                        { "condition", item.condition.ToString() },
                        { "id", item.info.itemid },
                        { "amount", item.amount },
                        { "skinid", item.skin },
                        { "position", item.position },
                        { "blueprintTarget", item.blueprintTarget },
                        { "dataInt", item.instanceData?.dataInt ?? 0 }
                    };

                    if (!string.IsNullOrEmpty(item.text))
                        itemdata["text"] = item.text;

                    var heldEnt = item.GetHeldEntity();

                    if (heldEnt != null)
                    {
                        var projectiles = heldEnt.GetComponent<BaseProjectile>();

                        if (projectiles != null)
                        {
                            var magazine = projectiles.primaryMagazine;

                            if (magazine != null)
                            {
                                itemdata.Add("magazine", new Dictionary<string, object>
                                {
                                    { magazine.ammoType.itemid.ToString(), magazine.contents }
                                });
                            }
                        }
                    }

                    if (item?.contents?.itemList != null)
                    {
                        var contents = new List<object>();

                        foreach (var itemContains in item.contents.itemList)
                        {
                            contents.Add(new Dictionary<string, object>
                            {
                                { "id", itemContains.info.itemid },
                                { "amount", itemContains.amount }
                            });
                        }

                        itemdata["items"] = contents;
                    }

                    itemlist.Add(itemdata);
                }

                data.Add("items", itemlist);
            }

            var sign = entity as Signage;
            if (sign != null && sign.textureIDs != null)
            {
                data.Add("sign", new Dictionary<string, object>
                {
                    { "locked", sign.IsLocked() }
                });

                var signData = (Dictionary<string, object>)data["sign"];

                for (var num = 0; num < sign.textureIDs.Length; num++)
                {
                    var textureId = sign.textureIDs[num];
                    if (textureId == 0)
                        continue;

                    var imageByte = FileStorage.server.Get(textureId, FileStorage.Type.png, sign.net.ID);
                    if (imageByte != null)
                    {
                        signData.Add($"texture{num}", Convert.ToBase64String(imageByte));
                    }
                }

                signData["amount"] = sign.textureIDs.Length;
            }

            var lights = entity as AdvancedChristmasLights;
            if (lights != null)
            {
                data.Add("points", lights.points.Select(x => new { x.normal, x.point }));
                data.Add("animationStyle", lights.animationStyle);
            }

            if (copyData.SaveShare)
            {
                var sleepingBag = entity as SleepingBag;

                if (sleepingBag != null)
                {
                    data.Add("sleepingbag", new Dictionary<string, object>
                    {
                        { "niceName", sleepingBag.niceName },
                        { "deployerUserID", sleepingBag.deployerUserID },
                        { "isPublic", sleepingBag.IsPublic() }
                    });
                }

                var cupboard = entity as BuildingPrivlidge;

                if (cupboard != null)
                {
                    data.Add("cupboard", new Dictionary<string, object>
                    {
                        { "authorizedPlayers", cupboard.authorizedPlayers.Select(y => y.userid).ToList() }
                    });
                }

                var autoTurret = entity as AutoTurret;

                if (autoTurret != null)
                {
                    data.Add("autoturret", new Dictionary<string, object>
                    {
                        { "authorizedPlayers", autoTurret.authorizedPlayers.Select(p => p.userid).ToList() }
                    });
                }
            }

            var cctvRc = entity as CCTV_RC;
            if (cctvRc != null)
            {
                data.Add("cctv", new Dictionary<string, object>
                {
                    { "yaw", cctvRc.yawAmount },
                    { "pitch", cctvRc.pitchAmount },
                    { "rcIdentifier", cctvRc.rcIdentifier }
                });
            }

            var vendingMachine = entity as VendingMachine;

            if (vendingMachine != null)
            {
                var sellOrders = new List<object>();

                foreach (var vendItem in vendingMachine.sellOrders.sellOrders)
                {
                    sellOrders.Add(new Dictionary<string, object>
                    {
                        { "itemToSellID", vendItem.itemToSellID },
                        { "itemToSellAmount", vendItem.itemToSellAmount },
                        { "currencyID", vendItem.currencyID },
                        { "currencyAmountPerItem", vendItem.currencyAmountPerItem },
                        { "inStock", vendItem.inStock },
                        { "currencyIsBP", vendItem.currencyIsBP },
                        { "itemToSellIsBP", vendItem.itemToSellIsBP }
                    });
                }

                data.Add("vendingmachine", new Dictionary<string, object>
                {
                    { "shopName", vendingMachine.shopName },
                    { "isBroadcasting", vendingMachine.IsBroadcasting() },
                    { "sellOrders", sellOrders }
                });
            }

            var ioEntity = entity as IOEntity;

            if (ioEntity != null)
            {
                var ioData = new Dictionary<string, object>();
                var inputs = ioEntity.inputs.Select(input => new Dictionary<string, object>
                    {
                        { "connectedID", input.connectedTo.entityRef.uid.Value },
                        { "connectedToSlot", input.connectedToSlot },
                        { "niceName", input.niceName },
                        { "type", (int)input.type }
                    }).Cast<object>().ToList();

                ioData.Add("inputs", inputs);

                var outputs = new List<object>();
                foreach (var output in ioEntity.outputs)
                {
                    var ioConnection = new Dictionary<string, object>
                    {
                        { "connectedID", output.connectedTo.entityRef.uid.Value },
                        { "connectedToSlot", output.connectedToSlot },
                        { "niceName", output.niceName },
                        { "type", (int)output.type },
                        { "linePoints", output.linePoints?.ToList() ?? new List<Vector3>() }
                    };

                    outputs.Add(ioConnection);
                }

                ioData.Add("outputs", outputs);
                ioData.Add("oldID", ioEntity.net.ID.Value);
                var electricalBranch = ioEntity as ElectricalBranch;
                if (electricalBranch != null)
                {
                    ioData.Add("branchAmount", electricalBranch.branchAmount);
                }

                var counter = ioEntity as PowerCounter;
                if (counter != null)
                {
                    ioData.Add("targetNumber", counter.GetTarget());
                }

                var timerSwitch = ioEntity as TimerSwitch;
                if (timerSwitch != null)
                {
                    ioData.Add("timerLength", timerSwitch.timerLength);
                }

                var rfBroadcaster = ioEntity as IRFObject;
                if (rfBroadcaster != null)
                {
                    ioData.Add("frequency", rfBroadcaster.GetFrequency());
                }

                data.Add("IOEntity", ioData);
            }

            return data;
        }

        private object FindBestHeight(HashSet<Dictionary<string, object>> entities, Vector3 startPos)
        {
            var maxHeight = 0f;

            foreach (var entity in entities)
            {
                var prefab = (string)entity["prefabname"];
                if (prefab.Contains("/foundation/") || prefab.Contains("/foundation.triangle/"))
                {
                    var foundHeight = GetGround((Vector3)entity["position"]);

                    if (foundHeight != null)
                    {
                        var height = (Vector3)foundHeight;

                        if (height.y > maxHeight)
                            maxHeight = height.y;
                    }
                }
            }

            maxHeight += 1f;

            return maxHeight;
        }

        private bool FindRayEntity(Vector3 sourcePos, Vector3 sourceDir, out Vector3 point, out BaseEntity entity,
            int rayLayer)
        {
            RaycastHit hitinfo;
            entity = null;
            point = Vector3.zero;

            if (!Physics.Raycast(sourcePos, sourceDir, out hitinfo, 1000f, rayLayer))
                return false;

            entity = hitinfo.GetEntity();
            point = hitinfo.point;

            return true;
        }

        private void FixSignage(Signage sign, byte[] imageBytes, int index)
        {
            if (!_signSizes.ContainsKey(sign.ShortPrefabName))
                return;

            var size = Math.Max(sign.paintableSources.Length, 1);
            if (sign.textureIDs == null || sign.textureIDs.Length != size)
            {
                Array.Resize(ref sign.textureIDs, size);
            }

            var resizedImage = ImageResize(imageBytes, _signSizes[sign.ShortPrefabName].Width,
                _signSizes[sign.ShortPrefabName].Height);

            sign.textureIDs[index] = FileStorage.server.Store(resizedImage, FileStorage.Type.png, sign.net.ID);
        }

        private object GetGround(Vector3 pos)
        {
            RaycastHit hitInfo;
            pos += new Vector3(0, 100, 0);

            if (Physics.Raycast(pos, Vector3.down, out hitInfo, 200, _groundLayer))
                return hitInfo.point;

            return null;
        }

        private int GetItemId(int itemId)
        {
            if (ReplaceItemId.ContainsKey(itemId))
                return ReplaceItemId[itemId];

            return itemId;
        }

        private bool HasAccess(IPlayer player, string permName)
        {
            return player.IsAdmin || player.HasPermission(permName);
        }

        private byte[] ImageResize(byte[] imageBytes, int width, int height)
        {
            Bitmap resizedImage = new Bitmap(width, height),
                sourceImage = new Bitmap(new MemoryStream(imageBytes));

            Graphics.FromImage(resizedImage).DrawImage(sourceImage, new Rectangle(0, 0, width, height),
                new Rectangle(0, 0, sourceImage.Width, sourceImage.Height), GraphicsUnit.Pixel);

            var ms = new MemoryStream();
            resizedImage.Save(ms, ImageFormat.Png);

            return ms.ToArray();
        }

        private string Lang(string key, string userId = null, params object[] args) =>
            string.Format(lang.GetMessage(key, this, userId), args);

        private Vector3 NormalizePosition(Vector3 initialPos, Vector3 currentPos, float diffRot)
        {
            var transformedPos = currentPos - initialPos;
            var newX = transformedPos.x * (float)Math.Cos(-diffRot) +
                       transformedPos.z * (float)Math.Sin(-diffRot);
            var newZ = transformedPos.z * (float)Math.Cos(-diffRot) -
                       transformedPos.x * (float)Math.Sin(-diffRot);

            transformedPos.x = newX;
            transformedPos.z = newZ;

            return transformedPos;
        }

        private PasteData Paste(ICollection<Dictionary<string, object>> entities, Dictionary<string, object> protocol,
            bool ownership, Vector3 startPos, IPlayer player, bool stability, float rotationCorrection,
            float heightAdj, bool auth, Action callback, Action<BaseEntity> callbackSpawned, string filename, bool checkPlaced)
        {
            //Settings

            var isItemReplace = !protocol.ContainsKey("items");

            var eulerRotation = new Vector3(0f, rotationCorrection * 57.2958f, 0f);
            var quaternionRotation = Quaternion.Euler(eulerRotation);

            var pasteData = new PasteData
            {
                HeightAdj = heightAdj,
                IsItemReplace = isItemReplace,
                Entities = entities,
                Player = player,
                BasePlayer = player.Object as BasePlayer,
                QuaternionRotation = quaternionRotation,
                StartPos = startPos,
                Stability = stability,
                Auth = auth,
                Ownership = ownership,
                CallbackFinished = callback,
                CallbackSpawned = callbackSpawned,
                Filename = filename,
                CheckPlaced = checkPlaced
            };

            NextTick(() => PasteLoop(pasteData));

            return pasteData;
        }

        private void PasteLoop(PasteData pasteData)
        {
            if (pasteData.Cancelled)
            {
                UndoLoop(new HashSet<BaseEntity>(pasteData.PastedEntities), pasteData.Player,
                    pasteData.PastedEntities.Count);
                
                return;
            }

            var entities = pasteData.Entities;
            var todo = entities.Take(_config.PasteBatchSize).ToArray();

            foreach (var data in todo)
            {
                entities.Remove(data);

                var prefabname = (string)data["prefabname"];
#if DEBUG
                Puts($"{nameof(PasteLoop)}: Entity {prefabname}");
#endif

                var skinid = ulong.Parse(data["skinid"].ToString());
                var pos = (Vector3)data["position"];
                var rot = (Quaternion)data["rotation"];

                var ownerId = pasteData.BasePlayer?.userID ?? 0;
                if (data.ContainsKey("ownerid"))
                {
#if DEBUG
                    Puts($"{nameof(PasteLoop)}: Convert.ToUInt64 1077");
#endif
                    ownerId = Convert.ToUInt64(data["ownerid"]);
                }

                if (pasteData.CheckPlaced && CheckPlaced(prefabname, pos, rot))
                    continue;

                if (prefabname.Contains("pillar"))
                    continue;

                // Used to copy locks for no reason in previous versions (is included in the slots info so no need to copy locks) so just skipping them.if (prefabname.Contains("locks"))
                    continue;

                var entity = GameManager.server.CreateEntity(prefabname, pos, rot);

                if (entity == null)
                    continue;

                var transform = entity.transform;
                transform.position = pos;
                transform.rotation = rot;

                if (pasteData.BasePlayer != null)
                    entity.SendMessage("SetDeployedBy", pasteData.BasePlayer, SendMessageOptions.DontRequireReceiver);

                if (pasteData.Ownership)
                    entity.OwnerID = ownerId;

                var buildingBlock = entity as BuildingBlock;

                if (buildingBlock != null)
                {
                    buildingBlock.blockDefinition = PrefabAttribute.server.Find<Construction>(buildingBlock.prefabID);
                    if (buildingBlock.skinID != 10220) buildingBlock.skinID = 0uL;
                    buildingBlock.SetGrade((BuildingGrade.Enum)data["grade"]);
                    if (!pasteData.Stability)
                        buildingBlock.grounded = true;
                }

                var decayEntity = entity as DecayEntity;

                if (decayEntity != null)
                {
                    if (pasteData.BuildingId == 0)
                        pasteData.BuildingId = BuildingManager.server.NewBuildingID();

                    decayEntity.AttachToBuilding(pasteData.BuildingId);
                }

                var stabilityEntity = entity as StabilityEntity;

                if (stabilityEntity != null)
                {
                    if (!stabilityEntity.grounded)
                    {
                        stabilityEntity.grounded = true;
                        pasteData.StabilityEntities.Add(stabilityEntity);
                    }
                }

                if (buildingBlock == null)
                    entity.skinID = skinid;

                entity.Spawn();

                var baseCombat = entity as BaseCombatEntity;

                if (buildingBlock != null)
                {
                    buildingBlock.SetHealthToMax();
                    buildingBlock.SendNetworkUpdate();
                    buildingBlock.UpdateSkin();
                }
                else if (baseCombat != null)
                    baseCombat.SetHealth(baseCombat.MaxHealth());

                pasteData.PastedEntities.AddRange(TryPasteSlots(entity, data, pasteData));

                var box = entity as StorageContainer;
                if (box != null)
                {
                    if (box.inventory == null)
                    {
                        box.inventory = new ItemContainer();
                        box.inventory.ServerInitialize(null, box.inventorySlots);
                        box.inventory.GiveUID();
                        box.inventory.entityOwner = box;
                    }
                    else box.inventory.Clear();

                    var items = new List<object>();

                    if (data.ContainsKey("items"))
                        items = data["items"] as List<object>;

                    foreach (var itemDef in items)
                    {
                        var item = itemDef as Dictionary<string, object>;
                        var itemid = Convert.ToInt32(item["id"]);
                        var itemamount = Convert.ToInt32(item["amount"]);
                        var itemskin = ulong.Parse(item["skinid"].ToString());
                        var itemcondition = Convert.ToSingle(item["condition"]);
                        var dataInt = 0;
                        if (item.ContainsKey("dataInt"))
                        {
                            dataInt = Convert.ToInt32(item["dataInt"]);
                        }

                        var growableEntity = entity as GrowableEntity;
                        if (growableEntity != null)
                        {
                            if (data.ContainsKey("genes"))
                            {
                                var genesData = (int)data["genes"];

                                if (genesData > 0)
                                {
                                    GrowableGeneEncoding.DecodeIntToGenes(genesData, growableEntity.Genes);
                                }
                            }

                            if (data.ContainsKey("hasParent"))
                            {
                                var isParented = (bool)data["hasParent"];

                                if (isParented)
                                {
                                    RaycastHit hitInfo;

                                    if (Physics.Raycast(growableEntity.transform.position, Vector3.down, out hitInfo,.5f, Rust.Layers.DefaultDeployVolumeCheck))
                                    {
                                        var parentEntity = hitInfo.GetEntity();
                                        if (parentEntity != null)
                                        {
                                            growableEntity.SetParent(parentEntity, true);
                                        }
                                    }
                                }
                            }
                        }

                        if (pasteData.IsItemReplace)
                            itemid = GetItemId(itemid);

                        var i = ItemManager.CreateByItemID(itemid, itemamount, itemskin);

                        if (i != null)
                        {
                            i.condition = itemcondition;

                            if (item.ContainsKey("text"))
                                i.text = item["text"].ToString();

                            if (item.ContainsKey("blueprintTarget"))
                            {
                                var blueprintTarget = Convert.ToInt32(item["blueprintTarget"]);

                                if (pasteData.IsItemReplace)
                                    blueprintTarget = GetItemId(blueprintTarget);

                                i.blueprintTarget = blueprintTarget;
                            }

                            if (dataInt > 0)
                            {
                                i.instanceData = new ProtoBuf.Item.InstanceData()
                                {
                                    ShouldPool = false,
                                    dataInt = dataInt
                                };
                            }

                            if (item.ContainsKey("magazine"))
                            {
                                var heldent = i.GetHeldEntity();

                                if (heldent != null)
                                {
                                    var projectiles = heldent.GetComponent<BaseProjectile>();

                                    if (projectiles != null)
                                    {
                               
// ... [Code preview truncated due to length. Full source in attached file] ...

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