New code for Edit Tool 02/2023Not An Issue

Open you .cs file and replace all code with this code:

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Reflection;
using System.Text;
using Network;
using Newtonsoft.Json;
using Oxide.Core.Configuration;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;
using ProtoBuf;
using UnityEngine;

namespace Oxide.Plugins
{
    [Info("Edit Tool", "JakeRich", "1.0.4")]
    [Description("Modify entities in a map")]
    public class EditTool : RustPlugin
    {
        public static ulong ToolSkinID = 1175592586;
        public static string ToolItemShortname = "coal";
        public static string ToolName = "Edit Tool";
        public static EditTool _plugin;
        public static float EditToolDistance = 50f;
        public static UIManager UI;
        public static PlayerDataController<ToolPlayerData> PlayerData;

        private const string permUse = "edittool.use";

        private void Init()
        {
            _plugin = this;
            UI = new UIManager();
            PlayerData = new PlayerDataController<ToolPlayerData>();
            permission.RegisterPermission(permUse, this);
            for (ToolMode mode = ToolMode.Transform; mode < ToolMode.Last; mode++)
            {
                permission.RegisterPermission($"edittool.{mode.ToString().ToLower()}", this);
            }
        }

        private void Unload()
        {
            UI.Unload();
        }

        private void OnPlayerInput(BasePlayer player, InputState input)
        {
            if (!player.IsAdmin)
            {
                if (!permission.UserHasPermission(player.UserIDString, permUse))
                {
                    return;
                }
            }

            if (!HasEditTool(player))
            {
                UI.ToolUI.Hide(player);
                UI.EntityInfoLabel.Text = "";
                UI.EntityInfoLabel.Refresh(player);
                return;
            }

            UI.ToolUI.Show(player);

            ToolPlayerData data = PlayerData.Get(player);
            if (input.WasJustPressed(BUTTON.FIRE_THIRD))
            {
                data.SwitchMode();
            }

            BaseEntity entity;
            Vector3 hitPoint;
            if (!GetEntityLookingAt(player, out entity, out hitPoint, EditToolDistance))
            {
                NotLookingAtEntity(player);
            }
            if (entity == null)
            {
                NotLookingAtEntity(player);
            }
            else
            {
                LookingAtEntity(player, entity);
                UI.EntityInfoLabel.Refresh(player);
            }

            if (input.WasJustPressed(BUTTON.FIRE_PRIMARY))
            {
                if (input.IsDown(BUTTON.SPRINT))
                {
                    data.OnShiftLeftClick(entity, hitPoint);
                }
                else if (input.IsDown(BUTTON.RELOAD))
                {
                    data.OnReloadClick(entity, hitPoint);
                }
                else
                {
                    data.OnLeftClick(entity, hitPoint);
                }
            }
            if (input.WasJustPressed(BUTTON.FIRE_SECONDARY))
            {
                if (input.IsDown(BUTTON.SPRINT))
                {
                    data.OnShiftRightClick(entity, hitPoint);
                }
                else
                {
                    data.OnRightClick(entity, hitPoint);
                }
            }
            if (input.WasJustReleased(BUTTON.FIRE_PRIMARY))
            {
                data.OnLeftRelease();
            }
            if (input.WasJustReleased(BUTTON.FIRE_SECONDARY))
            {
                data.OnRightRelease();
            }
            data.OnPlayerInput(entity, input);
        }

        private void OnEntityKill(BaseNetworkable entity)
        {
            OreResourceEntity node = entity as OreResourceEntity;
            if (node == null)
            {
                return;
            }

            node._hotSpot?.Kill();
        }

        private void NotLookingAtEntity(BasePlayer player)
        {
            UI.EntityInfoLabel.Text = "";
            UI.EntityInfoLabel.Refresh(player);
        }

        private void LookingAtEntity(BasePlayer player, BaseEntity entity)
        {
            UI.EntityInfoLabel.Text = $"{entity.ShortPrefabName}";
        }

        public static bool IsEditTool(Item item)
        {
            if (item == null)
            {
                return false;
            }

            return item.skin == ToolSkinID;
        }

        public static bool HasEditTool(BasePlayer player)
        {
            Item item = player.GetActiveItem();
            if (item == null)
            {
                return false;
            }

            return IsEditTool(item);
        }

        #region Entity Raycast

        //public static int EditToolLayer = LayerMask.GetMask("AI", "Construction", "Deployed", "Default", "Debris", "Ragdoll", "Tree", "Terrain", "World", "Vehicle Movement");
        public static int EditToolLayer = int.MaxValue;

        public static bool GetEntityLookingAt(BasePlayer player, out BaseEntity entity, out Vector3 hitPoint, float distance = 5f, bool announceOnNotFound = false)
        {
            entity = null;
            RaycastHit raycastHit;
            Ray ray = player.eyes.BodyRay();

            if (!Physics.Raycast(ray, out raycastHit, distance, EditToolLayer))
            {
                hitPoint = Vector3.zero;
                return false;
            }
            else
            {
                hitPoint = raycastHit.point;
                entity = raycastHit.GetEntity();
                if (entity != null)
                {
                    return true;
                }
            }

            if (announceOnNotFound)
            {
                player.IPlayer.Message(GetLangMessage("NotLookingAtEntity", player));
            }
            return true;
        }

        #endregion Entity Raycast

        [ChatCommand("edittool")]
        private void GiveEditTool_Command(BasePlayer player, string command, string[] args)
        {
            if (!player.IsAdmin)
            {
                return;
            }

            GiveEditTool(player);
        }

        [ConsoleCommand("edittool.switchmode")]
        private void SwitchEditToolMode_ConsoleCommand(ConsoleSystem.Arg args)
        {
            ToolPlayerData data = PlayerData.Get(args.Player());
            if (data == null)
            {
                return;
            }

            data.SwitchMode();
        }

        public void GiveEditTool(BasePlayer player)
        {
            Item item = ItemManager.CreateByPartialName(ToolItemShortname, 1);
            if (item == null)
            {
                PrintError("WARNING! Failed to create edit tool!");
                return;
            }

            item.skin = ToolSkinID;
            item.name = ToolName;
            player.GiveItem(item);
        }

        public enum ToolMode
        {
            None = 0,
            Transform = 1,
            Clone = 2,
            EditData = 3,
            Spawn = 4,
            Diguise = 5,
            Last
        }

        public class ToolPlayerData : PlayerDataBase
        {
            public ToolMode Mode = ToolMode.None;

            //public string SavedPrefabName = "";
            //private Vector3 SavedPrefabPosition;
            //private Quaternion SavedPrefabRotation;
            //private byte[] savedBytes;
            //private BuildingGrade grade;
            private BaseEntity selectedEntity;

            private Vector3 lastTransformPosition;
            private Vector3 transformOffset;
            private float TranslateDistance;
            private EntitySaver _entitySaver = new EntitySaver();
            private Quaternion _lastRotation;

            public void SwitchMode()
            {
                if (!Player.IsAdmin)
                {
                    if (!_plugin.permission.UserHasPermission(Player.UserIDString, permUse))
                    {
                        Mode = ToolMode.None;
                        return;
                    }
                }

                OnLeaveMode(Mode);
                int loops = 0;
                while (loops < (int)ToolMode.Last * 2)
                {
                    Mode++;
                    loops++;
                    if (Mode >= ToolMode.Last)
                    {
                        Mode = ToolMode.Transform;
                    }
                    if (Mode == ToolMode.EditData)
                    {
                        if (EntityPropertiesLoaded() == false)
                        {
                            continue;
                        }
                    }

                    if (Mode == ToolMode.Spawn)
                    {
                        continue;
                    }

                    if (Mode == ToolMode.Diguise)
                    {
                        if (DisguiseLoaded() == false)
                        {
                            continue;
                        }
                    }

                    //Permission check
                    if (!Player.IsAdmin)
                    {
                        if (!_plugin.permission.UserHasPermission(Player.UserIDString, $"edittool.{Mode.ToString().ToLower()}"))
                        {
                            continue;
                        }
                    }

                    OnEnterMode(Mode);
                    break;
                }
            }

            public void OnLeaveMode(ToolMode mode)
            {
                DeselectEntity();
            }

            public void OnEnterMode(ToolMode mode)
            {
                UI.SwitchToolMode(Player, Mode);
            }

            public void OnShiftRightClick(BaseEntity entity, Vector3 hitPoint)
            {
                switch (Mode)
                {
                    case ToolMode.Clone:
                        {
                            if (entity == null)
                            {
                                return;
                            }

                            SavePrefabName(entity, true);
                            break;
                        }
                    case ToolMode.EditData:
                        {
                            selectedEntity = entity;
                            break;
                        }
                }
            }

            public void OnShiftLeftClick(BaseEntity entity, Vector3 hitPoint)
            {
                switch (Mode)
                {
                    case ToolMode.Clone:
                        {
                            SpawnPrefab(hitPoint, true);
                            break;
                        }
                    case ToolMode.EditData:
                        {
                            if (entity == null)
                            {
                                return;
                            }

                            CloneEntityData(selectedEntity, entity);
                            break;
                        }
                }
            }

            public void OnLeftClick(BaseEntity entity, Vector3 hitPoint)
            {
                switch (Mode)
                {
                    case ToolMode.Clone:
                        {
                            SpawnPrefab(hitPoint, false);
                            break;
                        }
                    case ToolMode.Transform:
                        {
                            if (entity == null)
                            {
                                return;
                            }

                            SelectEntity(entity);
                            TranslateDistance = Vector3.Distance(hitPoint, Player.eyes.position);
                            transformOffset = hitPoint - selectedEntity.transform.position;
                            break;
                        }
                    case ToolMode.EditData:
                        {
                            if (entity == null)
                            {
                                return;
                            }

                            GameObject obj = new GameObject();
                            //obj.Identity();
                            //obj.SetActive(true);
                            //collider.bounds.SetMinMax(-bounds, bounds);
                            obj.layer = (int)Rust.Layer.Construction;
                            obj.transform.position = Player.transform.position;
                            //var rigid = obj.AddComponent<Rigidbody>();
                            //rigid.isKinematic = true;
                            //rigid.useGravity = false;
                            //rigid.detectCollisions = true;
                            BoxCollider collider = obj.AddComponent<BoxCollider>();
                            collider.size = new Vector3(3f, 3f, 3f);
                            //collider.isTrigger = false;
                            //collider.enabled = true;
                            obj.SetActive(false);
                            Debug(string.Join(",", obj.GetComponents<Component>().Select(x => x.GetType().ToString()).ToArray()));
                            //Vector3 bounds = new Vector3(3f,3f,3f);
                            //_plugin.Puts($"Added collider! {obj.transform.position} {Player.transform.position} {obj.transform.localScale}");
                            break;
                        }
                }
            }

            public void OnLeftRelease()
            {
                switch (Mode)
                {
                    case ToolMode.Transform:
                        {
                            if (selectedEntity == null)
                            {
                                return;
                            }

                            if (selectedEntity.GetComponent<Rigidbody>() != null)
                            {
                                Vector3 velocity = (selectedEntity.transform.position - lastTransformPosition);
                                Debug($"Setting release velocity {velocity}");
                                selectedEntity.SetVelocity(velocity * 20);
                                selectedEntity.GetComponent<Rigidbody>().useGravity = true;
                            }
                            Debug(string.Join(",", selectedEntity.GetComponents<Component>().Select(x => x.GetType().ToString()).ToArray()));
                            DeselectEntity();
                            break;
                        }
                }
            }

            public void OnRightRelease()
            {
            }

            public void OnRightClick(BaseEntity entity, Vector3 hitPoint)
            {
                switch (Mode)
                {
                    case ToolMode.Clone:
                        {
                            if (entity == null)
                            {
                                return;
                            }

                            SavePrefabName(entity, false);
                            break;
                        }
                    case ToolMode.EditData:
                        {
                            if (entity == null)
                            {
                                return;
                            }

                            StartEditingEntityData(Player, entity);
                            break;
                        }
                }
            }

            public void OnReloadClick(BaseEntity entity, Vector3 hitPoint)
            {
            }

            public void OnPlayerInput(BaseEntity entity, InputState input)
            {
                switch (Mode)
                {
                    case ToolMode.Transform:
                        {
                            if (input.WasJustPressed(BUTTON.FIRE_SECONDARY))
                            {
                                _lastRotation = entity.transform.rotation;
                                SelectEntity(entity);
                            }
                            if (input.WasJustReleased(BUTTON.FIRE_SECONDARY))
                            {
                                DeselectEntity();
                            }
                            float translateSpeed = 0.4f;
                            if (input.IsDown(BUTTON.SPRINT))
                            {
                                translateSpeed = 1.2f;
                            }
                            if (input.IsDown(BUTTON.USE))
                            {
                                TranslateDistance = Mathf.MoveTowards(TranslateDistance, 0, translateSpeed);
                            }
                            if (input.IsDown(BUTTON.RELOAD))
                            {
                                TranslateDistance = Mathf.MoveTowards(TranslateDistance, EditToolDistance, translateSpeed);
                            }
                            if (input.IsDown(BUTTON.FIRE_SECONDARY))
                            {
                                RotationTick(input);
                            }
                            else
                            {
                                TransformTick();
                            }
                            break;
                        }
                }
            }

            private void SelectEntity(BaseEntity entity)
            {
                selectedEntity = entity;
            }

            private void DeselectEntity()
            {
                //Handling in TransformTick and RotationTick as performance impact isn't too bad
                //TryUpdateBuildingBlock(selectedEntity);
                selectedEntity = null;
                lastTransformPosition = default(Vector3);
            }

            private void TryUpdateBuildingBlock(BaseEntity entity)
            {
                BuildingBlock block = entity as BuildingBlock;
                if (block == null)
                {
                    return;
                }

                block.UpdateSkin(true);
            }

            private void TransformTick()
            {
                if (selectedEntity == null)
                {
                    return;
                }

                //_plugin.Puts($"SyncPosition: {selectedEntity.syncPosition}");
                Rigidbody rigid = selectedEntity.GetComponent<Rigidbody>();
                //Disable rigid body's gravity, as they keep trying to fall when moved around
                if (rigid != null)
                {
                    rigid.useGravity = false;
                }
                lastTransformPosition = selectedEntity.transform.position;
                selectedEntity.transform.position = Player.eyes.BodyRay().origin + Player.eyes.BodyRay().direction * TranslateDistance - transformOffset;
                //Have to manually trigger building blocks to update their collider serverside
                TryUpdateBuildingBlock(selectedEntity);
                if (selectedEntity is AnimatedBuildingBlock)
                {
                    //Have to change entity flags for doors to update their position on client
                    //So just change a useless flag
                    //selectedEntity.SetFlag(BaseEntity.Flags.Open, !selectedEntity.HasFlag(BaseEntity.Flags.Open));
                }

                //Manually kill and respawn entities to make them update their position
                {
                    NetWrite nw = Net.sv.StartWrite();
                    nw.PacketID(Message.Type.EntityDestroy);
                    nw.UInt32(selectedEntity.net.ID);
                    nw.UInt8(0);
                    nw.Send(new SendInfo(selectedEntity.net.group.subscribers));
                }
                selectedEntity.SendNetworkUpdateImmediate();
                if (selectedEntity is BuildingBlock)
                {
                    //Have to tell the client to update building block's position on client
                    //selectedEntity.ClientRPC(null, "RefreshSkin");
                }
            }

            private void RotationTick(InputState input)
            {
                float multiplier = 8f;
                if (selectedEntity == null)
                {
                    return;
                }

                Vector3 center = selectedEntity.CenterPoint();

                //This will be used to fix the entity rotating on the players look angle
                Vector3 eyeLeveled = Player.eyes.position;
                Vector3 centerLeveled = center;
                eyeLeveled.y = 0;
                centerLeveled.y = 0;
                Ray ray = new Ray(eyeLeveled, eyeLeveled - centerLeveled);

                Vector3 difference = (new Vector3((input.previous.aimAngles.x - input.current.aimAngles.x) * -1f,
                                                  (input.previous.aimAngles.y - input.current.aimAngles.y),
                                                   0)) * multiplier;
                selectedEntity.transform.RotateAround(center, Player.eyes.BodyRight(), (input.previous.aimAngles.x - input.current.aimAngles.x) * multiplier);
                selectedEntity.transform.RotateAround(center, Player.eyes.BodyUp(), (input.previous.aimAngles.y - input.current.aimAngles.y) * multiplier);
                float rollRotate = 0f;
                if (input.IsDown(BUTTON.USE))
                {
                    rollRotate = 2f;
                }
                if (input.IsDown(BUTTON.RELOAD))
                {
                    rollRotate = -2f;
                }
                if (input.IsDown(BUTTON.SPRINT))
                {
                    rollRotate *= 4f;
                }
                selectedEntity.transform.RotateAround(center, Player.eyes.BodyForward(), rollRotate);
                if (input.IsDown(BUTTON.DUCK))
                {
                    float rotMuli = 9f;
                    selectedEntity.transform.rotation = Quaternion.Euler(Mathf.Round(selectedEntity.transform.rotation.x * rotMuli) / rotMuli,
                                                                         Mathf.Round(selectedEntity.transform.rotation.y * rotMuli) / rotMuli,
                                                                         Mathf.Round(selectedEntity.transform.rotation.z * rotMuli) / rotMuli);
                }

                TryUpdateBuildingBlock(selectedEntity);
                //Manually kill and respawn entities to make them update their position
                
                {
                    NetWrite nw = Net.sv.StartWrite();
                    nw.PacketID(Message.Type.EntityDestroy);
                    nw.UInt32(selectedEntity.net.ID);
                    nw.UInt8(0);
                    nw.Send(new SendInfo(selectedEntity.net.group.subscribers));
                }
                selectedEntity.SendNetworkUpdateImmediate();
            }

            private void SavePrefabName(BaseEntity entity, bool fullClone)
            {
                _entitySaver.SaveEntity(entity, fullClone);
            }

            private void SpawnPrefab(Vector3 position, bool fullClone)
            {
                _entitySaver.SpawnEntity(position, fullClone);
            }
        }

        public class EntitySaver
        {
            //public bool FullClone = false;
            private ulong _ownerID = 0;

            private string _prefabName = "";
            private Vector3 lastPos;
            private Quaternion _rotation;
            private byte[] savedBytes = null;
            private BuildingGrade.Enum _grade = BuildingGrade.Enum.None;
            private Vector3 velocity;

            public void SaveEntity(BaseEntity entity, bool fullClone)
            {
                _prefabName = entity.PrefabName;
                _rotation = entity.transform.rotation;
                lastPos = entity.transform.position;
                if (entity is BuildingBlock)
                {
                    _grade = (entity as BuildingBlock).grade;
                }
                if (!fullClone)
                {
                    savedBytes = null;
                    return;
                }

                savedBytes = entity.GetSaveCache().ToArray();
                if (entity.GetComponent<ServerProjectile>() != null)
                {
                    velocity = (Vector3)typeof(ServerProjectile).GetField("_currentVelocity", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public).GetValue(entity.GetComponent<ServerProjectile>());
                }
            }

            public void SpawnEntity(Vector3 position, bool fullClone)
            {
                if (_prefabName == "")
                {
                    return;
                }

                BaseEntity entity = GameManager.server.CreateEntity(_prefabName, position, _rotation);
                if (entity == null)
                {
                    _plugin.PrintError("SpawnPrefab Failed!");
                }
                if (fullClone)
                {
                    entity.PreServerLoad();
                }
                GameObject.Destroy(entity.GetComponent<Spawnable>());
                if (entity is BuildingBlock && _grade > BuildingGrade.Enum.None)
                {
                    (entity as BuildingBlock).grade = _grade;
                }
                entity.Spawn();
                if (entity is BuildingBlock && _grade > BuildingGrade.Enum.None)
                {
                    (entity as BuildingBlock).SetGrade(_grade);
                    (entity as BuildingBlock).Heal(entity.MaxHealth());
                }
                if (!fullClone)
                {
                    return;
                }

                if (savedBytes == null)
                {
                    return;
                }

                Entity entityData = Entity.Deserialize(savedBytes);
                BaseNetworkable.LoadInfo loadInfo = new BaseNetworkable.LoadInfo() { fromDisk = true };
                loadInfo.msg = entityData;
                entity.Load(loadInfo);
                entity.PostServerLoad();
                entity.transform.position = position;
                SetupEntityIDs(entity);
                if (entity.GetComponent<ServerProjectile>() != null)
                {
                    entity.GetComponent<ServerProjectile>().InitializeVelocity(velocity);
                }
                if (entity is Signage)
                {
                    entity.SendNetworkUpdate();
                }
            }

            private void SetupEntityIDs(BaseEntity entity)
            {
                if (entity is StorageContainer)
                {
                    SetupItemContainerIDs((entity as StorageContainer).inventory);
                }
                else if (entity is BasePlayer)
                {
                    BasePlayer player = entity as BasePlayer;
                    SetupItemContainerIDs(player.inventory.containerBelt);
                    SetupItemContainerIDs(player.inventory.containerMain);
                    SetupItemContainerIDs(player.inventory.containerWear);
                }
                else if (entity is DroppedItemContainer)
                {
                    SetupItemContainerIDs((entity as DroppedItemContainer).inventory);
                }
            }

            private void SetupItemContainerIDs(ItemContainer container)
            {
                container.uid = Net.sv.TakeUID();
                foreach (Item item in container.itemList)
                {
                    SetupItem(item);
                }
            }

            private void SetupItem(Item item)
            {
                item.uid = Net.sv.TakeUID();
                if (item.contents != null)
                {
                    SetupItemContainerIDs(item.contents);
                }
                foreach (ItemMod mod in item.info.itemMods)
                {
                    mod.OnItemCreated(item);
                }
            }
        }

        public class UIManager
        {
            private UIImage Crosshair;
            public UILabel EntityInfoLabel;
            public UIBaseElement ToolUI;
            private UILabel ToolMode;

            public UIManager()
            {
                SetupUI_ToolUI();
                SetupUI_Crosshair();
            }

            public void Unload()
            {
                Crosshair?.HideAll();
                EntityInfoLabel?.HideAll();
                ToolMode?.HideAll();
            }

            private void SetupUI_Crosshair()
            {
                float dotSize = 0.007f * 0.20f;
                Crosshair = new UIImage(new Vector2(0.5f - dotSize, 0.5f - dotSize * 2), new Vector2(0.5f + dotSize, 0.5f + dotSize * 2), ToolUI);
                Crosshair.Image.Sprite = "assets/icons/circle_closed.png";
                EntityInfoLabel = new UILabel(new Vector2(0.4f, 0.50f), new Vector2(0.6f, 0.60f), "Entity", 12, "1 1 1 1", ToolUI, TextAnchor.MiddleCenter);
                EntityInfoLabel.AddOutline();
            }

            private void SetupUI_ToolUI()
            {
                ToolUI = new UIBaseElement(new Vector2(0, 0), new Vector2(1, 1));
                ToolUI.conditionalShow = delegate (BasePlayer player)
                {
                    Item item = player.GetActiveItem();
                    if (item == null)
                    {
                        return false;
                    }

                    return item.skin == ToolSkinID;
                };
                ToolMode = new UILabel(new Vector2(0.29f, 0.02f), new Vector2(0.39f, 0.12f), "Inactive", 16, "1 1 1 1", ToolUI, TextAnchor.MiddleRight);
                ToolMode.variableText = delegate (BasePlayer player)
                {
                    return $"{PlayerData.Get(player).Mode}";
                };
                ToolMode.AddOutline();
            }

            public void SwitchToolMode(BasePlayer player, ToolMode mode)
            {
                ToolMode.Refresh(player);
            }
        }

        #region Lang API

        public Dictionary<string, string> lang_en = new Dictionary<string, string>()
        {
            {"NotLookingAtEntity", "You aren't looking at an entity!" },
        };

        public static string GetLangMessage(string key, BasePlayer player)
        {
            return _plugin.lang.GetMessage(key, _plugin, player.UserIDString);
        }

        public static string GetLangMessage(string key, ulong player)
        {
            return _plugin.lang.GetMessage(key, _plugin, player.ToString());
        }

        public static string GetLangMessage(string key, string player)
        {
            return _plugin.lang.GetMessage(key, _plugin, player);
        }

        #endregion Lang API

        #region Entity Properties Integration

        [PluginReference]
        private RustPlugin EntityProperties;

        public static bool EntityPropertiesLoaded()
        {
            if (_plugin.EntityProperties == null)
            {
                return false;
            }

            return _plugin.EntityProperties.IsLoaded;
        }

        public static void StartEditingEntityData(BasePlayer player, BaseEntity entity)
        {
            if (!EntityPropertiesLoaded())
            {
                return;
            }

            _plugin.EntityProperties.CallHook("StartEditingEntity", player, entity);
        }

        public static void StopEditingEntityData(BasePlayer player)
        {
            if (!EntityPropertiesLoaded())
            {
                return;
            }

            _plugin.EntityProperties.CallHook("StopEditingEntity", player);
        }

        public static void CloneEntityData(BaseEntity source, BaseEntity target)
        {
            if (!EntityPropertiesLoaded())
            {
                return;
            }

            _plugin.EntityProperties.CallHook("CloneEntitySettings", source, target);
        }

        #endregion Entity Properties Integration

        #region Disguise Integration

        [PluginReference]
        private RustPlugin Disguise;

        public static bool DisguiseLoaded()
        {
            if (_plugin.Disguise == null)
            {
                return false;
            }

            return _plugin.Disguise.IsLoaded;
        }

        #endregion Disguise Integration

        #region Error Printing

        public static bool Debugging = true;

        public static void Debug(string format, params object[] args)
        {
            if (!Debugging)
            {
                return;
            }

            _plugin.Puts(format, args);
        }

        public static void Debug(object obj)
        {
            if (!Debugging)
            {
                return;
            }

            _plugin.Puts(obj.ToString());
        }

        public static void Error(string format, params object[] args)
        {
            _plugin.PrintError(format, args);
        }

        #endregion Error Printing

        #region PlayerData

        public class PlayerDataBase
        {
            [JsonIgnore]
            public BasePlayer Player { get; set; }

            public string UserID { get; set; } = "";

            public PlayerDataBase()
            {
            }

            public PlayerDataBase(BasePlayer player)
            {
                UserID = player.UserIDString;
                Player = player;
            }
        }

        public class PlayerDataController<T> where T : PlayerDataBase
        {
            [JsonProperty(Required = Required.Always)]
            private Dictionary<string, T> playerData { get; set; } = new Dictionary<string, T>();

            public T Get(string identifer)
            {
                T data;
                if (!playerData.TryGetValue(identifer, out data))
                {
                    data = Activator.CreateInstance<T>();
                    playerData[identifer] = data;
                }
                return data;
            }

            public T Get(ulong userID)
            {
                return Get(userID.ToString());
            }

            public T Get(BasePlayer player)
            {
                T data = Get(player.UserIDString);
                data.Player = player;
                return data;
            }
        }

        #endregion PlayerData

        #region Rust Classes In JSON

        public class JSONSpawnPoint
        {
            public float xPos { get; set; }
            public float yPos { get; set; }
            public float zPos { get; set; }
            public float xRot { get; set; }
            public float yRot { get; set; }
            public float zRot { get; set; }
            public float wRot { get; set; }

            public BasePlayer.SpawnPoint ToSpawnPoint()
            {
                BasePlayer.SpawnPoint newSpawn = new BasePlayer.SpawnPoint();

                newSpawn.pos.x = xPos;
                newSpawn.pos.y = yPos;
                newSpawn.pos.z = zPos;
                newSpawn.rot.x = xRot;
                newSpawn.rot.y = yRot;
                newSpawn.rot.z = zRot;
                newSpawn.rot.w = wRot;

                return newSpawn;
            }

            [JsonIgnore]
            public Vector3 Position
            {
                get { return new Vector3(xPos, yPos, zPos); }
                set { xPos = value.x; yPos = value.y; zPos = value.z; }
            }

            [JsonIgnore]
            public Quaternion Rotation
            {
                get { return new Quaternion(xRot, yRot, zRot, wRot); }
                set { xRot = value.x; yRot = value.y; zRot = value.z; wRot = value.w; }
            }

            public JSONSpawnPoint()
            {
            }

            public JSONSpawnPoint(Vector3 position, Quaternion rot)
            {
                Position = position;
                Rotation = rot;
            }
        }

        public class JSONEntity
        {
            public float xPos { get; set; }
            public float yPos { get; set; }
            public float zPos { get; set; }

            public float xRot { get; set; }
            public float yRot { get; set; }
            public float zRot { get; set; }
            public float wRot { get; set; }

            public string prefabName { get; set; }

            [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
            public BuildingGrade.Enum grade { get; set; }

            [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
            public int AssignedBaseID;

            [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
            public ulong OwnerID = 0;

            [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
            public JSONStorageContainer Inventory;

            [JsonIgnore]
            public Vector3 Position
            {
                get { return new Vector3(xPos, yPos, zPos); }
            }

            [JsonIgnore]
            public Quaternion Rotation
            {
                get { return new Quaternion(xRot, yRot, zRot, wRot); }
            }

            [JsonIgnore]
            public BaseEntity Entity;

            public JSONEntity(BaseEntity entity) : this(entity, entity.transform.position, entity.transform.rotation)
            {
            }

            public JSONEntity(BaseEntity entity, Vector3 position, Quaternion rotation)
            {
                this.xPos = position.x;
                this.yPos = position.y;
                this.zPos = position.z;
                this.xRot = rotation.x;
                this.yRot = rotation.y;
                this.zRot = rotation.z;
                this.wRot = rotation.w;
                this.prefabName = entity.PrefabName;
                OwnerID = entity.OwnerID;
                if (entity.GetType() == typeof(BuildingBlock))
                {
                    grade = ((BuildingBlock)entity).grade;
                }
            }

            public JSONEntity()
            {
            }

            private BaseEntity CreateEntity(bool floating = true)
            {
                GameObject obj = GameManager.server.CreatePrefab(prefabName, Position, Rotation, false);
                if (obj == null)
                {
                    return null;
                }

                BaseEntity entity = obj.GetComponent<BaseEntity>();

                GameObject.Destroy(obj.GetComponent<Spawnable>());

                obj.AwakeFromInstantiate();

                entity.OwnerID = OwnerID;

                Entity = entity;

                PreSpawn(entity);

                return entity;
            }

            public void PreSpawn(BaseEntity entity)
            {
                if (entity is BuildingBlock)
                {
                    (entity as BuildingBlock).grade = grade;
                }
            }

            public void PostSpawn(BaseEntity entity)
            {
                BaseCombatEntity combat = entity as BaseCombatEntity;
                if (combat != null)
                {
                    if (combat.healthFraction < 1f)
                    {
                        combat.SetHealth(entity.MaxHealth());
                    }
                }
            }

            public BaseEntity Spawn()
            {
                BaseEntity ent = CreateEntity(false);
                ent.Spawn();
                PostSpawn(ent);
                return ent;
            }

            public bool IsEntity(BaseEntity entity)
            {
                if (entity.transform.position != Position)
                {
                    return false;
                }

                if (entity.transform.rotation != Rotation)
                {
                    return false;
                }

                if (entity.PrefabName != prefabName)
                {
                    return false;
                }

                if (entity.OwnerID != OwnerID)
                {
                    return false;
                }

                return true;
            }
        }

        public class JSONStorageContainer
        {
            public int MaxRefills = -1; //-1 For unlimited
            public bool Locked = true;
            public bool PerPlayer = false;

            public JSONItemContainer SavedInventory = new JSONItemContainer();
        }

        public class JSONItemAmount
        {
            public string shortname = "";
            public int amount = 0;

            [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
            public ulong skinID = 0;

            [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
            public int slot = 0;

            public JSONItemAmount()
            {
            }

            public JSONItemAmount(string shortname, int amount = 1, ulong skinID = 0)
            {
                this.shortname = shortname;
                this.amount = amount;
                this.skinID = skinID;
            }

            public JSONItemAmount(ItemAmount itemAmount) : this(itemAmount.itemDef.shortname, (int)itemAmount.amount)
            {
            }

            public JSONItemAmount(Item item, int slot = 0) : this(item.info.shortname, item.amount, item.skin)
            {
                this.slot = slot + 1;
            }

            public int ItemID()
            {
                ItemDefinition item = ItemManager.itemList.FirstOrDefault(x => x.shortname == shortname);
                if (item == null)
                {
                    return -1;
                }

                return item.itemid;
            }

            public Item CreateItem()
            {
                Item item = ItemManager.CreateByPartialName(shortname, amount);
                if (item == null)
                {
                    return null;
                }

                item.skin = skinID;
                return item;
            }

            public void GiveToPlayer(BasePlayer player)
            {
                Item item = CreateItem();
                if (item != null)
                {
                    player.GiveItem(item);
                }
            }

            public void AddToContainer(ItemContainer container)
            {
                Item item = CreateItem();
                item.MoveToContainer(container, slot - 1, false);
            }
        }

        public class JSONItemContainer
        {
            public List<JSONItemAmount> Items = new List<JSONItemAmount>();

            public JSONItemContainer()
            {
            }

            public JSONItemContainer(ItemContainer container)
            {
                List<JSONItemAmount> items = new List<JSONItemAmount>();
                for (int i = 0; i < container.capacity; i++)
                {
                    Item item = container.GetSlot(i);
                    items.Add(new JSONItemAmount(item, i));
                }
                Items = items;
            }

            public void Load(ItemContainer container)
            {
                container.Clear();
                foreach (JSONItemAmount item in Items)
                {
                    item.AddToContainer(container);
                }
            }
        }

        #endregion Rust Classes In JSON

        #region Configuration Files

        public enum ConfigLocation
        {
            Data = 0,
            Config = 1,
            Logs = 2,
            Plugins = 3,
            Lang = 4,
            Custom = 5,
        }

        public class JSONFile<Type> where Type : class
        {
            private DynamicConfigFile _file;
            public string _name { get; set; }
            public Type Instance { get; set; }
            private ConfigLocation _location { get; set; }
            private string _path { get; set; }
            public bool SaveOnUnload = false;
            public bool Compressed = false;

            public JSONFile(string name, ConfigLocation location = ConfigLocation.Data, string path = null, string extension = ".json", bool saveOnUnload = false)
            {
                SaveOnUnload = saveOnUnload;
                _name = name.Replace(".json", "");
                _location = location;
                switch (location)
                {
                    case ConfigLocation.Data:
                        {
                            _path = $"{Oxide.Core.Interface.Oxide.DataDirectory}/{name}{extension}";
                            break;
                        }
                    case ConfigLocation.Config:
                        {
                            _path = $"{Oxide.Core.Interface.Oxide.ConfigDirectory}/{name}{extension}";
                            break;
                        }
                    case ConfigLocation.Logs:
                        {
                            _path = $"{Oxide.Core.Interface.Oxide.LogDirectory}/{name}{extension}";
                            break;
                        }
                    case ConfigLocation.Lang:
                        {
                            _path = $"{Oxide.Core.Interface.Oxide.LangDirectory}/{name}{extension}";
                            break;
                        }
                    case ConfigLocation.Custom:
                        {
                            _path = $"{path}/{name}{extension}";
                            break;
                        }
                }
                _file = new DynamicConfigFile(_path);
                Init();
            }

            public virtual void Init()
            {
                _plugin.OnRemovedFromManager.Add(new Action<Plugin, PluginManager>(Unload));
                Load();
            }

            public virtual void Load()
            {
                if (Compressed)
                {
                    LoadCompressed();
                    return;
                }

                if (!_file.Exists())
                {
                    Save();
                }
                Instance = _file.ReadObject<Type>();
                if (Instance == null)
                {
                    Instance = Activator.CreateInstance<Type>();
                    Save();
                }
                return;
            }

            private void LoadCompressed()
            {
                string str = _file.ReadObject<string>();
                if (str == null || str == "")
                {
                    Instance = Activator.CreateInstance<Type>();
                    return;
                }

                using (MemoryStream compressedStream = new MemoryStream(Convert.FromBase64String(str)))
                using (GZipStream zipStream = new GZipStream(compressedStream, CompressionMode.Decompress))
                using (MemoryStream resultStream = new MemoryStream())
                {
                    byte[] buffer = new byte[4096];
                    int read;

                    while ((read = zipStream.Read(buffer, 0, buffer.Length)) > 0)
                    {
                        resultStream.Write(buffer, 0, read);
                    }

                    Instance = JsonConvert.DeserializeObject<Type>(Encoding.UTF8.GetString(resultStream.ToArray()));
                }
            }

            public virtual void Save()
            {
                if (Compressed)
                {
                    SaveCompressed();
                    return;
                }

                _file.WriteObject(Instance);
                return;
            }

            private void SaveCompressed()
            {
                using (MemoryStream stream = new MemoryStream())
                {
                    using (GZipStream zipStream = new GZipStream(stream, CompressionMode.Compress))
                    {
                        byte[] bytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(Instance));
                        zipStream.Write(bytes, 0, bytes.Length);
                        zipStream.Close();
                        _file.WriteObject(Convert.ToBase64String(stream.ToArray()));
                    }
                }
            }

            public virtual void Reload()
            {
                Load();
            }

            private void Unload(Plugin sender, PluginManager manager)
            {
                if (SaveOnUnload)
                {
                    Save();
                }
            }
        }

        #endregion Configuration Files

        #region Jake's UI Framework

        private Dictionary<string, UICallbackComponent> UIButtonCallBacks { get; set; } = new Dictionary<string, UICallbackComponent>();

        private void OnButtonClick(ConsoleSystem.Arg arg)
        {
            UICallbackComponent button;
            if (UIButtonCallBacks.TryGetValue(arg.cmd.Name, out button))
            {
                button.InvokeCallback(arg);
                return;
            }

            Puts("Unknown button command: {0}", arg.cmd.Name);
        }

        public class UIElement : UIBaseElement
        {
            public CuiElement Element { get; protected set; }
            public UIOutline Outline { get; set; }
            public CuiRectTransformComponent transform { get; protected set; }

            public float FadeOut
            {
                get
                {
                    return Element == null ? _fadeOut : Element.FadeOut;
                }
                set
                {
                    if (Element != null)
                    {
                        Element.FadeOut = value;
                    }
                    _fadeOut = value;
                }
            }

            private float _fadeOut = 0f;

            public string Name { get { return Element.Name; } }

            public UIElement(UIBaseElement parent = null) : base(parent)
            {
            }

            public UIElement(Vector2 position, float width, float height, UIBaseElement parent = null) : this(position, new Vector2(position.x + width, position.y + height), parent)
            {
            }

            public UIElement(Vector2 min, Vector2 max, UIBaseElement parent = null) : base(min, max, parent)
            {
                transform = new CuiRectTransformComponent();
                Element = new CuiElement
                {
                    Name = CuiHelper.GetGuid(),
                    Parent = this._parent == null ? this.Parent : this._parent.Parent,
                    Components =
                        {
                            transform,
                        },
                    FadeOut = _fadeOut,
                };
                UpdatePlacement();

                Init();
            }

            public void AddOutline(string color = "0 0 0 1", string distance = "1 -1")
            {
                Outline = new UIOutline(color, distance);
                Element.Components.Add(Outline.component);
            }

            public virtual void Init()
            {
            }

            public override void Show(BasePlayer player, bool children = true)
            {
                if (this is UIElement)
                {
                    if (!CanShow(player))
                    {
                        _shouldShow = false;
                        return;
                    }
                    _shouldShow = true;

                    if (conditionalSize != null)
                    {
                        Vector2 returnSize = conditionalSize.Invoke(player);
                        if (returnSize != null)
                        {
                            SetSize(returnSize.x, returnSize.y);
                        }
                    }

                    if (conditionalPosition != null)
                    {
                        Vector2 returnPos = conditionalPosition.Invoke(player);
                        if (returnPos != null)
                        {
                            SetPosition(returnPos.x, returnPos.y);
                        }
                    }
                }
                if (AddPlayer(player))
                {
                    SafeAddUi(player, Element);
                }
                base.Show(player, children);
            }

            public override void Hide(BasePlayer player, bool children = true)
            {
                base.Hide(player, children);
                if (RemovePlayer(player))
                {
                    SafeDestroyUi(player, Element);
                }
            }

            public override void UpdatePlacement()
            {
                base.UpdatePlacement();
                if (transform != null)
                {
                    transform.AnchorMin = $"{globalPosition.x} {globalPosition.y}";
                    transform.AnchorMax = $"{globalPosition.x + globalSize.x} {globalPosition.y + globalSize.y}";
                }
                //RefreshAll();
            }

            public void SetPositionAndSize(CuiRectTransformComponent trans)
            {
                transform.AnchorMin = trans.AnchorMin;
                transform.AnchorMax = trans.AnchorMax;

                //_plugin.Puts($"POSITION [{transform.AnchorMin},{transform.AnchorMax}]");

                RefreshAll();
            }

            public void SetParent(UIElement element)
            {
                Element.Parent = element.Element.Name;
                UpdatePlacement();
            }

            public void SetParent(string parent)
            {
                Element.Parent = parent;
                Parent = parent;
            }
        }

        public class UIButton : UIElement, UICallbackComponent
        {
            public CuiButtonComponent buttonComponent { get; private set; }
            public CuiTextComponent textComponent { get; private set; }
            public UILabel Label { get; set; }
            private string _textColor { get; set; }
            private string _buttonText { get; set; }
            public string Text { set { textComponent.Text = value; } }
            public Func<BasePlayer, string> variableText { get; set; }

            public Action<ConsoleSystem.Arg> onCallback;

            private int _fontSize;

            public UIButton(Vector2 min = default(Vector2), Vector2 max = default(Vector2), string buttonText = "", string buttonColor = "0 0 0 0.85", string textColor = "1 1 1 1", int fontSize = 15, UIBaseElement parent = null) : base(min, max, parent)
            {
                buttonComponent = new CuiButtonComponent();

                _fontSize = fontSize;
                _textColor = textColor;
                _buttonText = buttonText;

                buttonComponent.Command = CuiHelper.GetGuid();
                buttonComponent.Color = buttonColor;

                Element.Components.Insert(0, buttonComponent);

                _plugin.cmd.AddConsoleCommand(buttonComponent.Command, _plugin, "OnButtonClick");

                _plugin.UIButtonCallBacks[buttonComponent.Command] = this;

                Label = new UILabel(new Vector2(0, 0), new Vector2(1, 1), fontSize: _fontSize, parent: this);

                textComponent = Label.text;

                Label.text.Align = TextAnchor.MiddleCenter;
                Label.text.Color = _textColor;
                Label.Text = _buttonText;
                Label.text.FontSize = _fontSize;
            }

            public UIButton(Vector2 position, float width, float height, string buttonText = "", string buttonColor = "0 0 0 0.85", string textColor = "1 1 1 1", int fontSize = 15, UIBaseElement parent = null) : this(position, new Vector2(position.x + width, position.y + height), buttonText, buttonColor, textColor, fontSize, parent)
            {
            }

            public override void Init()
            {
                base.Init();
            }

            public void AddChatCommand(string fullCommand)
            {
                if (fullCommand == null)
                {
                    return;
                }
                onCallback += (arg) =>
                {
                    arg.Player().IPlayer.Command($"chat.say \"/{fullCommand}\"");
                };
            }

            public void AddCallback(Action<BasePlayer> callback)
            {
                if (callback == null)
                {
                    return;
                }
                onCallback += (args) => { callback(args.Player()); };
            }

            public override void Show(BasePlayer player, bool children = true)
            {
                if (variableText != null)
                {
                    try
                    {
                        Text = variableText.Invoke(player);
                    }
                    catch (Exception ex)
                    {
                        _plugin.Puts($"UIButton.variableText failed!\n{ex}");
                    }
                }
                base.Show(player, children);
            }

            public void InvokeCallback(ConsoleSystem.Arg args)
            {
                if (onCallback == null)
                {
                    return;
                }

                onCallback.Invoke(args);
            }
        }

        public class UIBackgroundText : UIPanel
        {
            public UILabel Label;

            public UIBackgroundText(Vector2 min = default(Vector2), Vector2 max = default(Vector2), UIBaseElement parent = null, string backgroundColor = "0 0 0 0.85", string labelText = "", int fontSize = 12, string fontColor = "1 1 1 1", TextAnchor alignment = TextAnchor.MiddleCenter) : base(min, max, parent)
            {
                Label = new UILabel(new Vector2(0, 0), new Vector2(1, 1), labelText, fontSize, fontColor, parent, alignment);
            }
        }

        public class UILabel : UIElement
        {
            public CuiTextComponent text { get; private set; }

            public UILabel(Vector2 min = default(Vector2), Vector2 max = default(Vector2), string labelText = "", int fontSize = 12, string fontColor = "1 1 1 1", UIBaseElement parent = null, TextAnchor alignment = TextAnchor.MiddleCenter) : base(min, max, parent)
            {
                if (min == Vector2.zero && max == Vector2.zero)
                {
                    max = Vector2.one;
                }

                text = new CuiTextComponent();

                text.Text = labelText;
                ColorString = fontColor;
                text.Align = alignment;
                text.FontSize = fontSize;

                Element.Components.Insert(0, text);
            }

            public UILabel(Vector2 min, float width, float height, string labelText = "", int fontSize = 12, string fontColor = "1 1 1 1", UIBaseElement parent = null, TextAnchor alignment = TextAnchor.MiddleCenter) : this(min, new Vector2(min.x + width, min.y + height), labelText, fontSize, fontColor, parent, alignment)
            {
            }

            public string Text { set { if (value == null) { text.Text = ""; } else { text.Text = value; } text.Text = value; } } //I love single line statments
            public TextAnchor Allign { set { text.Align = value; } }
            public Color Color { set { text.Color = value.ToString(); } }
            public string ColorString { set { text.Color = value.Replace("f", ""); } } //Prevent me from breaking UI with 0.1f instead of 0.1

            public Func<BasePlayer, string> variableText { get; set; }
            public Func<BasePlayer, string> variableFontColor { get; set; }

            public override void Show(BasePlayer player, bool children = true)
            {
                if (variableText != null)
                {
                    try
                    {
                        Text = variableText.Invoke(player);
                    }
                    catch (Exception ex)
                    {
                        _plugin.Puts($"UILabel.variableText failed!\n{ex}");
                    }
                }
                if (variableFontColor != null)
                {
                    try
                    {
                        ColorString = variableFontColor.Invoke(player);
                    }
                    catch (Exception ex)
                    {
                        _plugin.Puts($"UILabel.variableFontColor failed!\n{ex}");
                    }
                }
                base.Show(player, children);
            }

            public override void Init()
            {
                base.Init();

                if (_parent != null)
                {
                    if (_parent is UIButton)
                    {
                        Element.Parent = (_parent as UIButton).Name;
                        transform.AnchorMin = $"{localPosition.x} {localPosition.y}";
                        transform.AnchorMax = $"{localPosition.x + localSize.x} {localPosition.y + localSize.y}";
                    }
                }
            }
        }

        public class UIImageBase : UIElement
        {
            public UIImageBase(Vector2 min, Vector2 max, UIBaseElement parent) : base(min, max, parent)
            {
            }

            private CuiNeedsCursorComponent needsCursor { get; set; }

            private bool requiresFocus { get; set; }

            public bool CursorEnabled
            {
                get
                {
                    return requiresFocus;
                }
                set
                {
                    if (value)
                    {
                        needsCursor = new CuiNeedsCursorComponent();
                        Element.Components.Add(needsCursor);
                    }
                    else
                    {
                        Element.Components.Remove(needsCursor);
                    }

                    requiresFocus = value;
                }
            }
        }

        public class UIPanel : UIImageBase
        {
            private CuiImageComponent panel;

            public string Color { get { return panel.Color; } set { panel.Color = value; } }
            public string Material { get { return panel.Material; } set { panel.Material = value; } }

            public Func<BasePlayer, string> variableColor { get; set; }

            public UIPanel(Vector2 min, Vector2 max, UIBaseElement parent = null, string color = "0 0 0 0.85") : base(min, max, parent)
            {
                panel = new CuiImageComponent
                {
                    Color = color,

it appears not to allow the full code, however the changes are within the text above, just replace to the last point in this code.

Merged post

The updated bits are:
Starting line 578:

                    //Have to change entity flags for doors to update their position on client
                    //So just change a useless flag
                    //selectedEntity.SetFlag(BaseEntity.Flags.Open, !selectedEntity.HasFlag(BaseEntity.Flags.Open));
                }

                //Manually kill and respawn entities to make them update their position
                {
                    NetWrite nw = Net.sv.StartWrite();
                    nw.PacketID(Message.Type.EntityDestroy);
                    nw.UInt32(selectedEntity.net.ID);
                    nw.UInt8(0);
                    nw.Send(new SendInfo(selectedEntity.net.group.subscribers));
                }​

and
Starting Line 644

                //Manually kill and respawn entities to make them update their position

                {
                    NetWrite nw = Net.sv.StartWrite();
                    nw.PacketID(Message.Type.EntityDestroy);
                    nw.UInt32(selectedEntity.net.ID);
                    nw.UInt8(0);
                    nw.Send(new SendInfo(selectedEntity.net.group.subscribers));
                }​

The code above is the replacement code starting on those lines. you will see the differences.

Locked automatically