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

FREE CopyPaste : 3.0.18 3.0.18

Нет прав для скачивания
C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using System.Collections.Generic;
using System;
using System.Linq;
using System.Reflection;
using UnityEngine;
using Oxide.Core;
using Facepunch;
using System.IO;
namespace Oxide.Plugins {
    [Info("Copy Paste", "Reneb", "3.0.18", ResourceId = 5981)]
    class CopyPaste : RustPlugin {
        //////////////////////////////////////////////////////////////////////////////////////////////////////////////
        // Static Fields
        //////////////////////////////////////////////////////////////////////////////////////////////////////////////
        string copyPermission = "copypaste.copy";
        string pastePermission = "copypaste.paste";
        string undoPermission = "copypaste.undo";
        string subDirectory = "copypaste/";
        int rayLayer = LayerMask.GetMask(new string[] {
            "Construction", "Deployed", "Tree", "Terrain", "Resource", "World", "Water", "Default", "Prevent Building"
        }
        );
        int copyLayer = LayerMask.GetMask("Construction", "Construction Trigger", "Trigger", "Deployed", "Tree", "AI");
        int collisionLayer = LayerMask.GetMask("Construction", "Construction Trigger", "Trigger", "Deployed", "Default");
        int terrainLayer = LayerMask.GetMask(new string[] {
            "Terrain", "World", "Water", "Default"
        }
        );
        int groundLayer = LayerMask.GetMask(new string[] {
            "Terrain", "Default"
        }
        );
        private FieldInfo codelock = typeof(CodeLock).GetField("code", BindingFlags.NonPublic | BindingFlags.Instance);
        private FieldInfo keycode = typeof(KeyLock).GetField("keyCode", BindingFlags.NonPublic | BindingFlags.Instance);
        private FieldInfo firstKeyCreated = typeof(KeyLock).GetField("firstKeyCreated", BindingFlags.NonPublic | BindingFlags.Instance);
        private MethodInfo inventoryClear = typeof(ItemContainer).GetMethod("Clear", BindingFlags.NonPublic | BindingFlags.Instance);
        private MethodInfo newbuildingid = typeof(BuildingBlock).GetMethod("NewBuildingID", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
        DataFileSystem datafile = Interface.GetMod().DataFileSystem;
        Dictionary<string, List<BaseEntity>> lastPastes = new Dictionary<string, List<BaseEntity>>();
        //////////////////////////////////////////////////////////////////////////////////////////////////////////////
        // General Methods
        //////////////////////////////////////////////////////////////////////////////////////////////////////////////
        string GetMsg(string key, object steamid = null) {
            return lang.GetMessage(key, this, steamid == null ? null : steamid.ToString());
        }
        bool hasAccess(BasePlayer player, string permissionName) {
            if (player.net.connection.authLevel > 1) return true;
            return permission.UserHasPermission(player.userID.ToString(), permissionName);
        }
        bool FindRayEntity(Vector3 sourcePos, Vector3 sourceDir, out Vector3 point, out BaseEntity entity) {
            RaycastHit hitinfo;
            entity = null;
            point = default(Vector3);
            if (!Physics.Raycast(sourcePos, sourceDir, out hitinfo, 1000f, rayLayer)) {
                return false;
            }
            point = hitinfo.point;
            entity = hitinfo.GetEntity();
            return true;
        }
        //////////////////////////////////////////////////////////////////////////////////////////////////////////////
        // Oxide Hooks
        //////////////////////////////////////////////////////////////////////////////////////////////////////////////
        void Loaded() {
            permission.RegisterPermission(copyPermission, this);
            permission.RegisterPermission(pastePermission, this);
            permission.RegisterPermission(undoPermission, this);
            lang.RegisterMessages(new Dictionary<string, string> {
                {
                    "This file is empty.", "This file is empty."
                }
                , {
                    "You don't have the permissions to use this command.", "You don't have the permissions to use this command."
                }
                , {
                    "Syntax: /paste TARGETFILENAME options values\r\nheight XX - Adjust the height\r\nblockcollision XX - blocks the entire paste if something the new building collides with something", "Syntax: /paste TARGETFILENAME options values\r\nheight XX - Adjust the height\r\nblockcollision XX - blocks the entire paste if something the new building collides with something"
                }
                , {
                    "Syntax: /placeback TARGETFILENAME options values\r\nheight XX - Adjust the height\r\ncheckplaced true/false - checks if parts of the house are already placed or not, if they are already placed, the building part will be removed", "Syntax: /placeback TARGETFILENAME options values\r\nheight XX - Adjust the height\r\ncheckplaced true/false - checks if parts of the house are already placed or not, if they are already placed, the building part will be removed"
                }
                , {
                    "Syntax: /paste or /placeback TARGETFILENAME options values\r\nheight XX - Adjust the height\r\nautoheight true/false - sets best height, carefull of the steep\r\ncheckplaced true/false - checks if parts of the house are already placed or not, if they are already placed, the building part will be removed \r\nblockcollision XX - blocks the entire paste if something the new building collides with something\r\ndeployables true/false - false to remove deployables\r\ninventories true/false - false to ignore inventories", "Syntax: /paste or /placeback TARGETFILENAME options values\r\nheight XX - Adjust the height\r\nautoheight true/false - sets best height, carefull of the steep\r\ncheckplaced true/false - checks if parts of the house are already placed or not, if they are already placed, the building part will be removed \r\nblockcollision XX - blocks the entire paste if something the new building collides with something\r\ndeployables true/false - false to remove deployables\r\ninventories true/false - false to ignore inventories"
                }
                , {
                    "You've successfully placed back the structure.", "You've successfully placed back the structure."
                }
                , {
                    "You've successfully pasted the structure.", "You've successfully pasted the structure."
                }
                , {
                    "Syntax: /copy TARGETFILENAME options values\r\n radius XX (default 3)\r\n mechanics proximity/building (default building)\r\nbuilding true/false (saves structures or not)\r\ndeployables true/false (saves deployables or not)\r\ninventories true/false (saves inventories or not)", "Syntax: /copy TARGETFILENAME options values\r\n radius XX (default 3)\r\n mechanics proximity/building (default building)\r\nbuilding true/false (saves structures or not)\r\ndeployables true/false (saves deployables or not)\r\ninventories true/false (saves inventories or not)"
                }
                , {
                    "Couldn't ray something valid in front of you.", "Couldn't ray something valid in front of you."
                }
                , {
                    "The structure was successfully copied as {0}", "The structure was successfully copied as {0}"
                }
                , {
                    "You must paste something before undoing it.", "You must paste something before undoing it."
                }
                , {
                    "You've successfully undid what you pasted.", "You've successfully undid what you pasted."
                }
            }
            , this);
        }
        //////////////////////////////////////////////////////////////////////////////////////////////////////////////
        // Copy
        //////////////////////////////////////////////////////////////////////////////////////////////////////////////
        bool isValid(BaseEntity entity) {
            return entity.GetComponentInParent<BuildingBlock>() || entity.GetComponentInParent<BaseCombatEntity>() || entity.GetComponentInParent<Spawnable>();
        }
        void TryCopyLock(BaseEntity lockableEntity, IDictionary<string, object> housedata) {
            var slotentity = lockableEntity.GetSlot(BaseEntity.Slot.Lock);
            if (slotentity != null) {
                var codedata = new Dictionary<string, object> {
                    {
                        "prefabname", slotentity.PrefabName
                    }
                }
                ;
                if (slotentity.GetComponent<CodeLock>()) {
                    codedata.Add("code", codelock.GetValue(slotentity.GetComponent<CodeLock>()).ToString());
                }
                else if (slotentity.GetComponent<KeyLock>()) {
                    var code = (int)keycode.GetValue(slotentity.GetComponent<KeyLock>());
                    if ((bool)firstKeyCreated.GetValue(slotentity.GetComponent<KeyLock>())) code |= 0x80;
                    codedata.Add("code", code.ToString());
                }
                housedata.Add("lock", codedata);
            }
        }
        object CopyByBuilding(Vector3 sourcePos, Vector3 sourceRot, float RotationCorrection, float range, bool saveBuildings, bool saveDeployables, bool saveInventories) {
            var rawData = new List<object>();
            var houseList = new List<BaseEntity>();
            var checkFrom = new List<Vector3> {
                sourcePos
            }
            ;
            uint buildingid = 0;
            int current = 0;
            try {
                while (true) {
                    if (current >= checkFrom.Count) break;
                    List<BaseEntity> list = Pool.GetList<BaseEntity>();
                    Vis.Entities<BaseEntity>(checkFrom[current], range, list, copyLayer);
                    for (int i = 0; i < list.Count; i++) {
                        var entity = list[i];
                        if (isValid(entity) && !houseList.Contains(entity)) {
                            houseList.Add(entity);
                            var buildingblock = entity.GetComponentInParent<BuildingBlock>();
                            if (buildingblock) {
                                if (buildingid == 0) buildingid = buildingblock.buildingID;
                                else if(buildingid != buildingblock.buildingID) continue;
                            }
                            if (!checkFrom.Contains(entity.transform.position)) checkFrom.Add(entity.transform.position);
                            if (!saveBuildings && entity.GetComponentInParent<BuildingBlock>() != null) continue;
                            if (!saveDeployables && (entity.GetComponentInParent<BuildingBlock>() == null && entity.GetComponent<BaseCombatEntity>() != null)) continue;
                            rawData.Add(EntityData(entity, sourcePos, sourceRot, entity.transform.position, entity.transform.rotation.ToEulerAngles(), RotationCorrection, saveInventories));
                        }
                    }
                    current++;
                }
            }
            catch (Exception e) {
                return e.Message;
            }
            return rawData;
        }
        object CopyByProximity(Vector3 sourcePos, Vector3 sourceRot, float RotationCorrection, float range, bool saveBuildings, bool saveDeployables, bool saveInventories) {
            var rawData = new List<object>();
            var houseList = new List<BaseEntity>();
            var checkFrom = new List<Vector3> {
                sourcePos
            }
            ;
            int current = 0;
            try {
                while (true) {
                    if (current >= checkFrom.Count) break;
                    List<BaseEntity> list = Pool.GetList<BaseEntity>();
                    Vis.Entities<BaseEntity>(checkFrom[current], range, list, copyLayer);
                    for (int i = 0; i < list.Count; i++) {
                        var entity = list[i];
                        if (isValid(entity) && !houseList.Contains(entity)) {
                            houseList.Add(entity);
                            if (!checkFrom.Contains(entity.transform.position)) checkFrom.Add(entity.transform.position);
                            if (!saveBuildings && entity.GetComponentInParent<BuildingBlock>() != null) continue;
                            if (!saveDeployables && (entity.GetComponentInParent<BuildingBlock>() == null && entity.GetComponent<BaseCombatEntity>() != null)) continue;
                            rawData.Add(EntityData(entity, sourcePos, sourceRot, entity.transform.position, entity.transform.rotation.ToEulerAngles(), RotationCorrection, saveInventories));
                        }
                    }
                    current++;
                }
            }
            catch (Exception e) {
                return e.Message;
            }
            return rawData;
        }
        enum CopyMechanics {
            Building, Proximity
        }
        object TryCopyFromSteamID(string steamid, string filename, string[] args) {
            ulong userid;
            if (!ulong.TryParse(steamid, out userid)) {
                return "First argument isn't a steamid";
            }
            var player = BasePlayer.FindByID(userid);
            if (player == null) return "Couldn't find the player";
            if (!player.IsConnected()) return "Player is not connected?";
            return TryCopyFromPlayer(player, filename, args);
        }
        object TryCopyFromPlayer(BasePlayer player, string filename, string[] args) {
            if (player == null) return "Player is null?";
            if (!player.IsConnected()) return "Player is not connected?";
            var ViewAngles = Quaternion.Euler(player.GetNetworkRotation());
            BaseEntity sourceEntity;
            Vector3 sourcePoint;
            if (!FindRayEntity(player.eyes.position, ViewAngles * Vector3.forward, out sourcePoint, out sourceEntity)) {
                return GetMsg("Couldn't ray something valid in front of you.", player.userID.ToString());
            }
            return TryCopy(sourcePoint, sourceEntity.transform.rotation.ToEulerAngles(), filename, ViewAngles.ToEulerAngles().y, args);
        }
        object TryCopy(Vector3 sourcePos, Vector3 sourceRot, string filename, float RotationCorrection, string[] args) {
            CopyMechanics copyMechanics = CopyMechanics.Building;
            float radius = 3f;
            bool saveInventories = true;
            bool saveDeployables = true;
            bool saveBuilding = true;
            for(int i = 0; ; i = i + 2) {
                if (i >= args.Length) break;
                if(i+1 >= args.Length) {
                    return GetMsg("Syntax: /copy TARGETFILENAME options values\r\n radius XX (default 3)\r\n mechanics proximity/building (default building)\r\nbuilding true/false (saves structures or not)\r\ndeployables true/false (saves deployables or not)\r\ninventories true/false (saves inventories or not)", null);
                }
                switch(args[i].ToLower()) {
                    case "r" : case "rad" : case "radius" : if(!float.TryParse(args[i+1], out radius)) {
                        return "radius must be a number";
                    }
                    break;
                    case "mechanics" : case "m" : case "mecha" : switch(args[i+1].ToLower()) {
                        case "building" : case "build" : case "b" : copyMechanics = CopyMechanics.Building;
                        break;
                        case "proximity" : case "prox" : case "p" : copyMechanics = CopyMechanics.Proximity;
                        break;
                    }
                    break;
                    case "i" : case "inventories" : case "inv" : if(!bool.TryParse(args[i + 1], out saveInventories)) {
                        return "save inventories needs to be true or false";
                    }
                    break;
                    case "b" : case "building" : case "structure" : if (!bool.TryParse(args[i + 1], out saveBuilding)) {
                        return "save buildings needs to be true or false";
                    }
                    break;
                    case "d" : case "deployables" : if (!bool.TryParse(args[i + 1], out saveDeployables)) {
                        return "save deployables needs to be true or false";
                    }
                    break;
                    default : return GetMsg("Syntax: /copy TARGETFILENAME options values\r\n radius XX (default 3)\r\n mechanics proximity/building (default building)\r\nbuilding true/false (saves structures or not)\r\ndeployables true/false (saves deployables or not)\r\ninventories true/false (saves inventories or not)", null);
                    break;
                }
            }
            return Copy(sourcePos, sourceRot, filename, RotationCorrection, copyMechanics, radius, saveBuilding, saveDeployables, saveInventories);
        }
        object Copy(Vector3 sourcePos, Vector3 sourceRot, string filename, float RotationCorrection, CopyMechanics copyMechanics, float range, bool saveBuildings, bool saveDeployables, bool saveInventories ) {
            var rawData = new List<object>();
            var copy = copyMechanics == CopyMechanics.Proximity ? CopyByProximity(sourcePos, sourceRot, RotationCorrection, range, saveBuildings, saveDeployables, saveInventories) : CopyByBuilding(sourcePos, sourceRot, RotationCorrection, range, saveBuildings, saveDeployables, saveInventories);
            ;
            if (copy is string) return copy;
            rawData = copy as List<object>;
            var defaultData = new Dictionary<string, object> {
                {
                    "position", new Dictionary<string, object> {
                        {
                            "x", sourcePos.x.ToString()
                        }
                        , {
                            "y", sourcePos.y.ToString()
                        }
                        , {
                            "z", sourcePos.z.ToString()
                        }
                    }
                }
                , {
                    "rotationy", sourceRot.y.ToString()
                }
                , {
                    "rotationdiff", RotationCorrection.ToString()
                }
            }
            ;
            string path = subDirectory + filename;
            var CopyData = Interface.GetMod().DataFileSystem.GetDatafile(path);
            CopyData.Clear();
            CopyData["default"] = defaultData;
            CopyData["entities"] = rawData;
            Interface.GetMod().DataFileSystem.SaveDatafile(path);
            return true;
        }
        Dictionary<string, object> EntityData(BaseEntity entity, Vector3 sourcePos, Vector3 sourceRot, Vector3 entPos, Vector3 entRot, float diffRot, bool saveInventories) {
            var normalizedPos = NormalizePosition(sourcePos, entPos, diffRot);
            var normalizedRot = entRot.y - diffRot;
            var data = new Dictionary<string, object> {
                {
                    "prefabname", entity.PrefabName
                }
                , {
                    "skinid", entity.skinID
                }
                , {
                    "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", normalizedRot.ToString()
                        }
                        , {
                            "z", entRot.z.ToString()
                        }
                        ,
                    }
                }
            }
            ;
            if (entity.HasSlot(BaseEntity.Slot.Lock)) TryCopyLock(entity, data);
            var buildingblock = entity.GetComponentInParent<BuildingBlock>();
            if (buildingblock != null ) {
                data.Add("grade", buildingblock.grade);
            }
            var box = entity.GetComponentInParent<StorageContainer>();
            if (box != null) {
                var itemlist = new List<object>();
                if (saveInventories) {
                    foreach (Item 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
                            }
                            ,
                        }
                        ;
                        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 != null) {
                            if(item.contents.itemList != null) {
                                var contents = new List<object>();
                                foreach (Item item2 in item.contents.itemList) {
                                    contents.Add(new Dictionary<string, object> {
                                        {
                                            "condition", item.condition.ToString()
                                        }
                                        , {
                                            "id", item.info.itemid
                                        }
                                        , {
                                            "amount", item.amount
                                        }
                                        , {
                                            "skinid", item.skin
                                        }
                                        , {
                                            "items", new List<object>()
                                        }
                                    }
                                    );
                                }
                                itemdata["items"] = contents;
                            }
                        }
                        itemlist.Add(itemdata);
                    }
                }
                data.Add("items", itemlist);
            }
            var sign = entity.GetComponentInParent<Signage>();
            if(sign != null) {
                var get = FileStorage.server.Get(sign.textureID, FileStorage.Type.png, sign.net.ID);
                data.Add("sign", new Dictionary<string, object> {
                    {
                        "locked", sign.IsLocked()
                    }
                }
                );
                if (sign.textureID > 0 && get != null) ((Dictionary<string, object>)data["sign"]).Add("texture", Convert.ToBase64String(get));
            }
            return data;
        }
        Vector3 NormalizePosition(Vector3 InitialPos, Vector3 CurrentPos, float diffRot) {
            var transformedPos = CurrentPos - InitialPos;
            var newX = (transformedPos.x * (float)System.Math.Cos(-diffRot)) + (transformedPos.z * (float)System.Math.Sin(-diffRot));
            var newZ = (transformedPos.z * (float)System.Math.Cos(-diffRot)) - (transformedPos.x * (float)System.Math.Sin(-diffRot));
            transformedPos.x = newX;
            transformedPos.z = newZ;
            return transformedPos;
        }
        //////////////////////////////////////////////////////////////////////////////////////////////////////////////
        // Placeback
        //////////////////////////////////////////////////////////////////////////////////////////////////////////////
        object TryPlaceback(string filename, BasePlayer player, string[] args) {
            string path = subDirectory + filename;
            if (datafile.ExistsDatafile(path)) {
            }
            var data = Interface.GetMod().DataFileSystem.GetDatafile(path);
            if (data["default"] == null || data["entities"] == null) {
                return GetMsg("This file is empty.", player.userID.ToString());
            }
            var defaultdata = data["default"] as Dictionary<string, object>;
            var pos = defaultdata["position"] as Dictionary<string, object>;
            var startPos = new Vector3(Convert.ToSingle(pos["x"]), Convert.ToSingle(pos["y"]), Convert.ToSingle(pos["z"]));
            var RotationCorrection = Convert.ToSingle(defaultdata["rotationdiff"]);
            return TryPaste(startPos, filename, player, RotationCorrection, args);
        }
        //////////////////////////////////////////////////////////////////////////////////////////////////////////////
        // Paste
        //////////////////////////////////////////////////////////////////////////////////////////////////////////////
        object TryPasteFromVector3(Vector3 startPos, Vector3 direction, string filename, string[] args) {
            return TryPaste(startPos, filename, null, direction.y, args);
        }
        object TryPasteFromSteamID(string steamid, string filename, string[] args) {
            ulong userid;
            if (!ulong.TryParse(steamid, out userid)) {
                return "First argument isn't a steamid";
            }
            var player = BasePlayer.FindByID(userid);
            if(player == null) return "Couldn't find the player";
            if (!player.IsConnected()) return "Player is not connected?";
            return TryPasteFromPlayer(player, filename, args);
        }
        object TryPasteFromPlayer(BasePlayer player, string filename, string[] args) {
            if (player == null) return "Player is null?";
            if (!player.IsConnected()) return "Player is not connected?";
            var ViewAngles = Quaternion.Euler(player.GetNetworkRotation());
            BaseEntity sourceEntity;
            Vector3 sourcePoint;
            if (!FindRayEntity(player.eyes.position, ViewAngles * Vector3.forward, out sourcePoint, out sourceEntity)) {
                return GetMsg("Couldn't ray something valid in front of you.", player.userID.ToString());
            }
            return TryPaste(sourcePoint, filename, player, ViewAngles.ToEulerAngles().y, args);
        }
        object TryPaste(Vector3 startPos, string filename, BasePlayer player, float RotationCorrection, string[] args) {
            var steamid = player == null ? null : player.userID.ToString();
            string path = subDirectory + filename;
            if (datafile.ExistsDatafile(path)) {
            }
            var data = Interface.GetMod().DataFileSystem.GetDatafile(path);
            if(data["default"] == null || data["entities"] == null) {
                return GetMsg("This file is empty.", steamid);
            }
            float heightAdj = 0f;
            float blockCollision = 0f;
            bool checkPlaced = false;
            bool autoHeight = false;
            bool inventories = true;
            bool deployables = true;
            for (int i = 0; ; i = i + 2) {
                if (i >= args.Length) break;
                if (i + 1 >= args.Length) {
                    return GetMsg("Syntax: /paste or /placeback TARGETFILENAME options values\r\nheight XX - Adjust the height\r\nautoheight true/false - sets best height, carefull of the steep\r\ncheckplaced true/false - checks if parts of the house are already placed or not, if they are already placed, the building part will be removed \r\nblockcollision XX - blocks the entire paste if something the new building collides with something\r\ndeployables true/false - false to remove deployables\r\ninventories true/false - false to ignore inventories", steamid);
                }
                switch (args[i].ToLower()) {
                    case "autoheight" : if (!bool.TryParse(args[i + 1], out autoHeight)) {
                        return "autoheight must be true or false";
                    }
                    break;
                    case "height" : if (!float.TryParse(args[i + 1], out heightAdj)) {
                        return "height must be a number";
                    }
                    break;
                    case "checkplaced" : if (!bool.TryParse(args[i + 1], out checkPlaced)) {
                        return "checkplaced must be true or false";
                    }
                    break;
                    case "blockcollision" : if (!float.TryParse(args[i + 1], out blockCollision)) {
                        return "blockcollision must be a number, 0 will deactivate the option";
                    }
                    break;
                    case "deployables" : if (!bool.TryParse(args[i + 1], out deployables)) {
                        return "deployables must be true or false";
                    }
                    break;
                    case "inventories" : if (!bool.TryParse(args[i + 1], out inventories)) {
                        return "inventories must be true or false";
                    }
                    break;
                    default : return GetMsg("Syntax: /paste or /placeback TARGETFILENAME options values\r\nheight XX - Adjust the height\r\nautoheight true/false - sets best height, carefull of the steep\r\ncheckplaced true/false - checks if parts of the house are already placed or not, if they are already placed, the building part will be removed \r\nblockcollision XX - blocks the entire paste if something the new building collides with something\r\ndeployables true/false - false to remove deployables\r\ninventories true/false - false to ignore inventories", steamid);
                    break;
                }
            }
            startPos.y += heightAdj;
            var preloadData = PreLoadData(data["entities"] as List<object>, startPos, RotationCorrection, deployables, inventories);
            if(autoHeight) {
                var bestHeight = FindBestHeight(preloadData, startPos);
                if (bestHeight is string) {
                    return bestHeight;
                }
                heightAdj = (float)bestHeight - startPos.y;
                FixPreloadData(preloadData, heightAdj);
            }
            if (blockCollision > 0f) {
                var collision = CheckCollision(preloadData, startPos, blockCollision);
                if(collision is string) {
                    return collision;
                }
            }
            return Paste(preloadData, startPos, player, checkPlaced);
        }
        object GetGround(Vector3 pos) {
            RaycastHit hitInfo;
            if (Physics.Raycast(pos, Vector3.up, out hitInfo, groundLayer)) {
                return hitInfo.point;
            }
            if (Physics.Raycast(pos, Vector3.down, out hitInfo, groundLayer)) {
                return hitInfo.point;
            }
            return null;
        }
        object FindBestHeight(List<Dictionary<string, object>> entities, Vector3 startPos) {
            float minHeight = 0f;
            float maxHeight = 0f;
            foreach(var entity in entities) {
                if(((string)entity["prefabname"]).Contains("/foundation/")) {
                    var foundHeight = GetGround((Vector3)entity["position"]);
                    if(foundHeight != null) {
                        var height = (Vector3)foundHeight;
                        if (height.y > maxHeight) maxHeight = height.y;
                        if (height.y < minHeight) minHeight = height.y;
                    }
                }
            }
            if (maxHeight - minHeight > 3f) return "The ground is too steep";
            return maxHeight;
        }
        void FixPreloadData(IList<Dictionary<string, object>> entities, float heightAdj) {
            foreach(var entity in entities) {
                var pos = ((Vector3)entity["position"]);
                pos.y += heightAdj;
                entity["position"] = pos;
            }
        }
        List<Dictionary<string, object>> PreLoadData(List<object> entities, Vector3 startPos, float RotationCorrection, bool deployables, bool inventories) {
            var eulerRotation = new Vector3(0f, RotationCorrection, 0f);
            var quaternionRotation = Quaternion.EulerRotation(eulerRotation);
            var preloaddata = new List<Dictionary<string, object>>();
            foreach(var entity in entities) {
                var data = entity as Dictionary<string, object>;
                if (!deployables && !data.ContainsKey("grade")) continue;
                var pos = (Dictionary<string, object>)data["pos"];
                var rot = (Dictionary<string, object>)data["rot"];
                var fixedRotation = Quaternion.EulerRotation(eulerRotation + new Vector3(Convert.ToSingle(rot["x"]), Convert.ToSingle(rot["y"]), Convert.ToSingle(rot["z"])));
                var tempPos = quaternionRotation * (new Vector3(Convert.ToSingle(pos["x"]), Convert.ToSingle(pos["y"]), Convert.ToSingle(pos["z"])));
                Vector3 newPos = tempPos + startPos;
                data.Add("position", newPos);
                data.Add("rotation", fixedRotation);
                if (!inventories && data.ContainsKey("items")) data["items"] = new List<object>();
                preloaddata.Add(data);
            }
            return preloaddata;
        }
        void TryPasteLock(BaseEntity lockableEntity, Dictionary<string, object> structure) {
            BaseEntity lockentity = null;
            if (structure.ContainsKey("lock")) {
                var lockdata = structure["lock"] as Dictionary<string, object>;
                lockentity = GameManager.server.CreateEntity((string)lockdata["prefabname"], Vector3.zero, new Quaternion(), true);
                if (lockentity != null) {
                    lockentity.gameObject.Identity();
                    lockentity.SetParent(lockableEntity, "lock");
                    lockentity.OnDeployed(lockableEntity);
                    lockentity.Spawn();
                    lockableEntity.SetSlot(BaseEntity.Slot.Lock, lockentity);
                    if (lockentity.GetComponent<CodeLock>()) {
                        var code = (string)lockdata["code"];
                        if (!string.IsNullOrEmpty(code)) {
                            var @lock = lockentity.GetComponent<CodeLock>();
                            codelock.SetValue(@lock, code);
                            @lock.SetFlag(BaseEntity.Flags.Locked, true);
                        }
                    }
                    else if (lockentity.GetComponent<KeyLock>()) {
                        var code = Convert.ToInt32(lockdata["code"]);
                        var @lock = lockentity.GetComponent<KeyLock>();
                        if ((code & 0x80) != 0) {
                            keycode.SetValue(@lock, (code & 0x7F));
                            firstKeyCreated.SetValue(@lock, true);
                            @lock.SetFlag(BaseEntity.Flags.Locked, true);
                        }
                    }
                }
            }
        }
        object CheckCollision(List<Dictionary<string, object>> entities, Vector3 startPos, float radius) {
            foreach (var entityobj in entities) {
                var pos = (Vector3)entityobj["position"];
                var rot = (Quaternion)entityobj["rotation"];
                foreach(var collider in Physics.OverlapSphere(pos, radius, collisionLayer)) {
                    return string.Format("Something is blocking the paste ({0})", collider.gameObject.name.ToString());
                }
            }
            return true;
        }
        List<BaseEntity> Paste(List<Dictionary<string, object>> entities, Vector3 startPos, BasePlayer player, bool checkPlaced) {
            bool unassignid = true;
            uint buildingid = 0;
            var pastedEntities = new List<BaseEntity>();
            foreach(var data in entities) {
                try {
                    var prefabname = (string)data["prefabname"];
                    var skinid = ulong.Parse(data["skinid"].ToString());
                    var pos = (Vector3)data["position"];
                    var rot = (Quaternion)data["rotation"];
                    bool isplaced = false;
                    if (checkPlaced) {
                        foreach (var col in Physics.OverlapSphere(pos, 1f)) {
                            var ent = col.GetComponentInParent<BaseEntity>();
                            if (ent != null) {
                                if (ent.PrefabName == prefabname && ent.transform.position == pos && ent.transform.rotation == rot) {
                                    isplaced = true;
                                    break;
                                }
                            }
                        }
                    }
                    if (isplaced) continue;
                    var entity = GameManager.server.CreateEntity(prefabname, pos, rot, true);
                    if (entity != null) {
                        entity.transform.position = pos;
                        entity.transform.rotation = rot;
                        entity.SendMessage("SetDeployedBy", player, SendMessageOptions.DontRequireReceiver);
                        var buildingblock = entity.GetComponentInParent<BuildingBlock>();
                        if (buildingblock != null) {
                            buildingblock.blockDefinition = PrefabAttribute.server.Find<Construction>(buildingblock.prefabID);
                            buildingblock.SetGrade((BuildingGrade.Enum)data["grade"]);
                            if (unassignid) {
                                buildingid = (uint)newbuildingid.Invoke(buildingblock, null);
                                unassignid = false;
                            }
                            buildingblock.buildingID = buildingid;
                        }
                        entity.skinID = skinid;
                        entity.Spawn();
                        bool killed = false;
                        if (killed) continue;
                        var basecombat = entity.GetComponentInParent<BaseCombatEntity>();
                        if (basecombat != null) {
                            basecombat.ChangeHealth(basecombat.MaxHealth());
                        }
                        if (entity.HasSlot(BaseEntity.Slot.Lock)) {
                            TryPasteLock(entity, data);
                        }
                        var box = entity.GetComponentInParent<StorageContainer>();
                        if (box != null) {
                            inventoryClear.Invoke(box.inventory, null);
                            var items = data["items"] as List<object>;
                            var itemlist = new List<ItemAmount>();
                            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 i = ItemManager.CreateByItemID(itemid, itemamount, itemskin);
                                if (i != null) {
                                    i.condition = itemcondition;
                                    if (item.ContainsKey("magazine")) {
                                        var magazine = item["magazine"] as Dictionary<string, object>;
                                        var ammotype = int.Parse(magazine.Keys.ToArray()[0]);
                                        var ammoamount = int.Parse(magazine[ammotype.ToString()].ToString());
                                        var heldent = i.GetHeldEntity();
                                        if (heldent != null) {
                                            var projectiles = heldent.GetComponent<BaseProjectile>();
                                            if (projectiles != null) {
                                                projectiles.primaryMagazine.ammoType = ItemManager.FindItemDefinition(ammotype);
                                                projectiles.primaryMagazine.contents = ammoamount;
                                            }
                                        }
                                    }
                                    i?.MoveToContainer(box.inventory).ToString();
                                }
                            }
                            ;
                        }
                        var sign = entity.GetComponentInParent<Signage>();
                        if (sign != null) {
                            var signData = data["sign"] as Dictionary<string, object>;
                            if (signData.ContainsKey("texture")) {
                                var stream = new MemoryStream();
                                var stringSign = Convert.FromBase64String(signData["texture"].ToString());
                                stream.Write(stringSign, 0, stringSign.Length);
                                sign.textureID = FileStorage.server.Store(stream, FileStorage.Type.png, sign.net.ID);
                                stream.Position = 0;
                                stream.SetLength(0);
                            }
                            if (Convert.ToBoolean(signData["locked"])) sign.SetFlag(BaseEntity.Flags.Locked, true);
                            sign.SendNetworkUpdate();
                        }
                        pastedEntities.Add(entity);
                    }
                }
                catch(Exception e) {
                    PrintError(string.Format("Trying to paste {0} send this error: {1}", data["prefabname"].ToString(), e.Message));
                }
            }
            return pastedEntities;
        }
        //////////////////////////////////////////////////////////////////////////////////////////////////////////////
        // Undo
        //////////////////////////////////////////////////////////////////////////////////////////////////////////////
        object TryUndo(BasePlayer player) {
            return TryUndo(player.userID.ToString());
        }
        object TryUndo(string steamid) {
            if (!lastPastes.ContainsKey(steamid)) {
                return GetMsg("You must paste something before undoing it.", steamid);
            }
            var success = Undo(lastPastes[steamid]);
            lastPastes.Remove(steamid);
            return success;
        }
        object Undo(List<BaseEntity> entities) {
            foreach(var entity in entities) {
                if (entity == null) continue;
                if (entity.isDestroyed) continue;
                entity.KillMessage();
            }
            return true;
        }
        //////////////////////////////////////////////////////////////////////////////////////////////////////////////
        // Chat commands
        //////////////////////////////////////////////////////////////////////////////////////////////////////////////
        [ChatCommand("paste")]
        void cmdChatPaste(BasePlayer player, string command, string[] args) {
            var steamid = player.userID.ToString();
            if (!hasAccess(player, pastePermission)) {
                SendReply(player, GetMsg("You don't have the permissions to use this command.", steamid));
                return;
            }
            if (args == null || args.Length == 0) {
                SendReply(player, GetMsg("Syntax: /paste or /placeback TARGETFILENAME options values\r\nheight XX - Adjust the height\r\nautoheight true/false - sets best height, carefull of the steep\r\ncheckplaced true/false - checks if parts of the house are already placed or not, if they are already placed, the building part will be removed \r\nblockcollision XX - blocks the entire paste if something the new building collides with something", steamid));
                return;
            }
            var loadname = args[0];
            var success = TryPasteFromPlayer(player, loadname, args.Skip(1).ToArray());
            if (success is string) {
                SendReply(player, (string)success);
                return;
            }
            if (lastPastes.ContainsKey(steamid)) lastPastes.Remove(steamid);
            lastPastes.Add(steamid, (List<BaseEntity>)success);
            SendReply(player, GetMsg("You've successfully pasted the structure.", steamid));
        }
        [ChatCommand("undo")]
        void cmdChatUndo(BasePlayer player, string command, string[] args) {
            var steamid = player.userID.ToString();
            if (!hasAccess(player, undoPermission)) {
                SendReply(player, GetMsg("You don't have the permissions to use this command.", steamid));
                return;
            }
            var success = TryUndo(player);
            if (success is string) {
                SendReply(player, (string)success);
                return;
            }
            SendReply(player, GetMsg("You've successfully undid what you pasted.", steamid));
        }
        [ChatCommand("placeback")]
        void cmdChatPlaceback(BasePlayer player, string command, string[] args) {
            var steamid = player.userID.ToString();
            i
// ... [Code preview truncated due to length. Full source in attached file] ...

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