From 132d293c3c7d0fba27a14044e8f4487c8bc8cd87 Mon Sep 17 00:00:00 2001
From: Thijs Wenker <me@thoys.nl>
Date: Wed, 30 Jan 2019 03:15:32 +0100
Subject: [PATCH] skip child entities of mismatching entityHostType when
 copy/delete/duplication of entities

---
 scripts/system/edit.js                        | 51 ++++++++++++-------
 .../system/libraries/entitySelectionTool.js   | 44 ++++++++++++----
 2 files changed, 68 insertions(+), 27 deletions(-)

diff --git a/scripts/system/edit.js b/scripts/system/edit.js
index 2e175d72a4..9d807264aa 100644
--- a/scripts/system/edit.js
+++ b/scripts/system/edit.js
@@ -1608,30 +1608,42 @@ function sortSelectedEntities(selected) {
     return sortedEntities;
 }
 
-function recursiveDelete(entities, childrenList, deletedIDs) {
+function recursiveDelete(entities, childrenList, deletedIDs, entityHostType) {
+    var wantDebug = false;
     var entitiesLength = entities.length;
-    for (var i = 0; i < entitiesLength; i++) {
+    var initialPropertySets = Entities.getMultipleEntityProperties(entities);
+    var entityHostTypes = Entities.getMultipleEntityProperties(entities, 'entityHostType');
+    for (var i = 0; i < entitiesLength; ++i) {
         var entityID = entities[i];
+
+        if (entityHostTypes[i].entityHostType !== entityHostType) {
+            if (wantDebug) {
+                console.log("Skipping deletion of entity " + entityID + " with conflicting entityHostType: " +
+                    entityHostTypes[i].entityHostType);
+            }
+            continue;
+        }
+
         var children = Entities.getChildrenIDs(entityID);
         var grandchildrenList = [];
-        recursiveDelete(children, grandchildrenList, deletedIDs);
-        var initialProperties = Entities.getEntityProperties(entityID);
+        recursiveDelete(children, grandchildrenList, deletedIDs, entityHostType);
         childrenList.push({
             entityID: entityID,
-            properties: initialProperties,
+            properties: initialPropertySets[i],
             children: grandchildrenList
         });
         deletedIDs.push(entityID);
         Entities.deleteEntity(entityID);
     }
 }
+
 function unparentSelectedEntities() {
     if (SelectionManager.hasSelection()) {
         var selectedEntities = selectionManager.selections;
         var parentCheck = false;
 
         if (selectedEntities.length < 1) {
-            Window.notifyEditError("You must have an entity selected inorder to unparent it.");
+            Window.notifyEditError("You must have an entity selected in order to unparent it.");
             return;
         }
         selectedEntities.forEach(function (id, index) {
@@ -1694,21 +1706,24 @@ function deleteSelectedEntities() {
         SelectionManager.saveProperties();
         var savedProperties = [];
         var newSortedSelection = sortSelectedEntities(selectionManager.selections);
-        for (var i = 0; i < newSortedSelection.length; i++) {
+        var entityHostTypes = Entities.getMultipleEntityProperties(newSortedSelection, 'entityHostType');
+        for (var i = 0; i < newSortedSelection.length; ++i) {
             var entityID = newSortedSelection[i];
             var initialProperties = SelectionManager.savedProperties[entityID];
-            if (!initialProperties.locked) {
-                var children = Entities.getChildrenIDs(entityID);
-                var childList = [];
-                recursiveDelete(children, childList, deletedIDs);
-                savedProperties.push({
-                    entityID: entityID,
-                    properties: initialProperties,
-                    children: childList
-                });
-                deletedIDs.push(entityID);
-                Entities.deleteEntity(entityID);
+            if (initialProperties.locked ||
+                (initialProperties.avatarEntity && initialProperties.owningAvatarID !== MyAvatar.sessionUUID)) {
+                continue;
             }
+            var children = Entities.getChildrenIDs(entityID);
+            var childList = [];
+            recursiveDelete(children, childList, deletedIDs, entityHostTypes[i].entityHostType);
+            savedProperties.push({
+                entityID: entityID,
+                properties: initialProperties,
+                children: childList
+            });
+            deletedIDs.push(entityID);
+            Entities.deleteEntity(entityID);
         }
 
         if (savedProperties.length > 0) {
diff --git a/scripts/system/libraries/entitySelectionTool.js b/scripts/system/libraries/entitySelectionTool.js
index 83cd010337..01e5f6e22b 100644
--- a/scripts/system/libraries/entitySelectionTool.js
+++ b/scripts/system/libraries/entitySelectionTool.js
@@ -193,14 +193,25 @@ SelectionManager = (function() {
         that._update(true, caller);
     };
     
-    that.addChildrenEntities = function(parentEntityID, entityList) {
+    that.addChildrenEntities = function(parentEntityID, entityList, entityHostType) {
+        var wantDebug = false;
         var children = Entities.getChildrenIDs(parentEntityID);
+        var entityHostTypes = Entities.getMultipleEntityProperties(children, 'entityHostType');
         for (var i = 0; i < children.length; i++) {
             var childID = children[i];
+
+            if (entityHostTypes[i].entityHostType !== entityHostType) {
+                if (wantDebug) {
+                    console.log("Skipping addition of entity " + childID + " with conflicting entityHostType: " +
+                        entityHostTypes[i].entityHostType);
+                }
+                continue;
+            }
+
             if (entityList.indexOf(childID) < 0) {
                 entityList.push(childID);
             }
-            that.addChildrenEntities(childID, entityList);
+            that.addChildrenEntities(childID, entityList, entityHostType);
         }
     };
 
@@ -250,12 +261,15 @@ SelectionManager = (function() {
         SelectionManager.saveProperties();
         
         // build list of entities to duplicate by including any unselected children of selected parent entities
-        Object.keys(that.savedProperties).forEach(function(originalEntityID) {
-            if (entitiesToDuplicate.indexOf(originalEntityID) < 0) {
+        var originalEntityIDs = Object.keys(that.savedProperties);
+        var entityHostTypes = Entities.getMultipleEntityProperties(originalEntityIDs, 'entityHostType');
+        for (var i = 0; i < originalEntityIDs.length; i++) {
+            var originalEntityID = originalEntityIDs[i];
+            if (entitiesToDuplicate.indexOf(originalEntityID) === -1) {
                 entitiesToDuplicate.push(originalEntityID);
             }
-            that.addChildrenEntities(originalEntityID, entitiesToDuplicate);
-        });
+            that.addChildrenEntities(originalEntityID, entitiesToDuplicate, entityHostTypes[i].entityHostType);
+        }
         
         // duplicate entities from above and store their original to new entity mappings and children needing re-parenting
         for (var i = 0; i < entitiesToDuplicate.length; i++) {
@@ -319,7 +333,7 @@ SelectionManager = (function() {
     };
 
     // Create the entities in entityProperties, maintaining parent-child relationships.
-    // @param entityPropertites {array} - Array of entity property objects
+    // @param entityProperties {array} - Array of entity property objects
     that.createEntities = function(entityProperties) {
         var entitiesToCreate = [];
         var createdEntityIDs = [];
@@ -362,15 +376,27 @@ SelectionManager = (function() {
 
     that.copySelectedEntities = function() {
         var entityProperties = Entities.getMultipleEntityProperties(that.selections);
+        var entityHostTypes = Entities.getMultipleEntityProperties(that.selections, 'entityHostType');
         var entities = {};
         entityProperties.forEach(function(props) {
             entities[props.id] = props;
         });
 
-        function appendChildren(entityID, entities) {
+        function appendChildren(entityID, entities, entityHostType) {
+            var wantDebug = false;
             var childrenIDs = Entities.getChildrenIDs(entityID);
+            var entityHostTypes = Entities.getMultipleEntityProperties(childrenIDs, 'entityHostType');
             for (var i = 0; i < childrenIDs.length; ++i) {
                 var id = childrenIDs[i];
+
+                if (entityHostTypes[i].entityHostType !== entityHostType) {
+                    if (wantDebug) {
+                        console.warn("Skipping deletion of entity " + id + " with conflicting entityHostType: " +
+                            entityHostTypes[i].entityHostType);
+                    }
+                    continue;
+                }
+
                 if (!(id in entities)) {
                     entities[id] = Entities.getEntityProperties(id); 
                     appendChildren(id, entities);
@@ -380,7 +406,7 @@ SelectionManager = (function() {
 
         var len = entityProperties.length;
         for (var i = 0; i < len; ++i) {
-            appendChildren(entityProperties[i].id, entities);
+            appendChildren(entityProperties[i].id, entities, entityHostTypes[i].entityHostType);
         }
 
         for (var id in entities) {