History

apply delete rules down linked hierarchy

Andrew Meadows committed 7 years ago

Commit 8ab70221 parent 470a45c25 files · +401 −279Browse files

Showing the changes to libraries/entities/src/EntityScriptingInterface.cpp (1 of 25 files). Show all

Unified · Split

libraries/entities/src/EntityScriptingInterface.cpp+40−30
@@ -966,42 +966,52 @@ void EntityScriptingInterface::deleteEntity(const QUuid& id) { · 965 unmodified lines
966966
967967 _activityTracking.deletedEntityCount++;
968968
969+ if (!_entityTree) {
970+ return;
971+ }
972+
969973 EntityItemID entityID(id);
970− bool shouldSendDeleteToServer = true;
971974
972975 // If we have a local entity tree set, then also update it.
973− if (_entityTree) {
974− _entityTree->withWriteLock([&] {
975− EntityItemPointer entity = _entityTree->findEntityByEntityItemID(entityID);
976− if (entity) {
977− auto nodeList = DependencyManager::get<NodeList>();
978− const QUuid myNodeID = nodeList->getSessionUUID();
979− if (entity->isAvatarEntity() && !entity->isMyAvatarEntity()) {
980− // don't delete other avatar's avatarEntities
981− shouldSendDeleteToServer = false;
982− return;
983− }
984−
985− if (entity->getLocked()) {
986− shouldSendDeleteToServer = false;
987− } else {
988− // only delete non-domain entities, domain entities will round trip through the server filters
989− if (!entity->isDomainEntity() || _entityTree->isServerlessMode()) {
990− shouldSendDeleteToServer = false;
991− _entityTree->deleteEntity(entityID);
976+ SetOfEntities entitiesToDeleteImmediately;
977+ SetOfEntities domainEntities;
978+ _entityTree->withWriteLock([&] {
979+ EntityItemPointer entity = _entityTree->findEntityByEntityItemID(entityID);
980+ if (entity) {
981+ if (entity->isAvatarEntity() && !entity->isMyAvatarEntity()) {
982+ // don't delete other avatar's avatarEntities
983+ return;
984+ }
985+ if (entity->getLocked()) {
986+ return;
987+ }
992988
993− if (entity->isAvatarEntity() && getEntityPacketSender()->getMyAvatar()) {
994− getEntityPacketSender()->getMyAvatar()->clearAvatarEntity(entityID, false);
995− }
996− }
997− }
989+ // Deleting an entity has consequences for linked children: some can be deleted but others can't.
990+ // Local- and my-avatar-entities can be deleted immediately, but other-avatar-entities can't be deleted
991+ // by this context, and domain-entity deletes must rountrip through the entity-server for authorization.
992+ // So we recurse down the linked hierarchy and snarf children into two categories:
993+ // (a) entitiesToDeleteImmediately and (b) domainEntntities.
994+ if (entity->isDomainEntity()) {
995+ domainEntities.insert(entity);
996+ } else {
997+ entitiesToDeleteImmediately.insert(entity);
998+ const auto sessionID = DependencyManager::get<NodeList>()->getSessionUUID();
999+ entity->collectChildrenForDelete(entitiesToDeleteImmediately, domainEntities, sessionID);
9981000 }
999− });
1000− }
1001+ if (!entitiesToDeleteImmediately.empty()) {
1002+ _entityTree->deleteEntitiesByPointer(entitiesToDeleteImmediately);
1003+ }
1004+ }
1005+ });
10011006
1002− // if at this point, we know the id, and we should still delete the entity, send the update to the entity server
1003− if (shouldSendDeleteToServer) {
1004− getEntityPacketSender()->queueEraseEntityMessage(entityID);
1007+ foreach (auto entity, entitiesToDeleteImmediately) {
1008+ if (entity->isMyAvatarEntity()) {
1009+ getEntityPacketSender()->getMyAvatar()->clearAvatarEntity(entityID, false);
1010+ }
1011+ }
1012+ // finally ask entity-server to delete domainEntities
1013+ foreach (auto entity, domainEntities) {
1014+ getEntityPacketSender()->queueEraseEntityMessage(entity->getID());
10051015 }
10061016 }
10071017