abide by domain-entity hierarchy deletion rules

This commit is contained in:
Andrew Meadows 2019-10-16 08:55:02 -07:00
parent 4e6a647718
commit 4159bc4862
8 changed files with 19 additions and 46 deletions

View file

@ -3235,7 +3235,7 @@ void EntityItem::retrieveMarketplacePublicKey() {
}); });
} }
void EntityItem::collectChildrenForDelete(SetOfEntities& entitiesToDelete, SetOfEntities& domainEntities, const QUuid& sessionID) const { void EntityItem::collectChildrenForDelete(SetOfEntities& entitiesToDelete, const QUuid& sessionID) const {
// Deleting an entity has consequences for its children, however there are rules dictating what can be deleted. // Deleting an entity has consequences for its children, however there are rules dictating what can be deleted.
// This method helps enforce those rules for the children of entity (not for this entity). // This method helps enforce those rules for the children of entity (not for this entity).
for (SpatiallyNestablePointer child : getChildren()) { for (SpatiallyNestablePointer child : getChildren()) {
@ -3246,10 +3246,8 @@ void EntityItem::collectChildrenForDelete(SetOfEntities& entitiesToDelete, SetOf
(childEntity->isMyAvatarEntity() || childEntity->getOwningAvatarID() == sessionID))) { (childEntity->isMyAvatarEntity() || childEntity->getOwningAvatarID() == sessionID))) {
if (entitiesToDelete.find(childEntity) == entitiesToDelete.end()) { if (entitiesToDelete.find(childEntity) == entitiesToDelete.end()) {
entitiesToDelete.insert(childEntity); entitiesToDelete.insert(childEntity);
childEntity->collectChildrenForDelete(entitiesToDelete, domainEntities, sessionID); childEntity->collectChildrenForDelete(entitiesToDelete, sessionID);
} }
} else if (childEntity->isDomainEntity()) {
domainEntities.insert(childEntity);
} }
} }
} }

View file

@ -543,7 +543,7 @@ public:
static QString _marketplacePublicKey; static QString _marketplacePublicKey;
static void retrieveMarketplacePublicKey(); static void retrieveMarketplacePublicKey();
void collectChildrenForDelete(SetOfEntities& entitiesToDelete, SetOfEntities& domainEntities, const QUuid& sessionID) const; void collectChildrenForDelete(SetOfEntities& entitiesToDelete, const QUuid& sessionID) const;
float getBoundingRadius() const { return _boundingRadius; } float getBoundingRadius() const { return _boundingRadius; }
void setSpaceIndex(int32_t index); void setSpaceIndex(int32_t index);

View file

@ -974,7 +974,6 @@ void EntityScriptingInterface::deleteEntity(const QUuid& id) {
// If we have a local entity tree set, then also update it. // If we have a local entity tree set, then also update it.
SetOfEntities entitiesToDeleteImmediately; SetOfEntities entitiesToDeleteImmediately;
SetOfEntities domainEntities;
_entityTree->withWriteLock([&] { _entityTree->withWriteLock([&] {
EntityItemPointer entity = _entityTree->findEntityByEntityItemID(entityID); EntityItemPointer entity = _entityTree->findEntityByEntityItemID(entityID);
if (entity) { if (entity) {
@ -988,15 +987,13 @@ void EntityScriptingInterface::deleteEntity(const QUuid& id) {
// Deleting an entity has consequences for linked children: some can be deleted but others can't. // Deleting an entity has consequences for linked children: some can be deleted but others can't.
// Local- and my-avatar-entities can be deleted immediately, but other-avatar-entities can't be deleted // Local- and my-avatar-entities can be deleted immediately, but other-avatar-entities can't be deleted
// by this context, and domain-entity deletes must rountrip through the entity-server for authorization. // by this context, and a domain-entity must rountrip through the entity-server for authorization.
// So we recurse down the linked hierarchy and snarf children into two categories:
// (a) entitiesToDeleteImmediately and (b) domainEntntities.
if (entity->isDomainEntity()) { if (entity->isDomainEntity()) {
domainEntities.insert(entity); getEntityPacketSender()->queueEraseEntityMessage(entity->getID());
} else { } else {
entitiesToDeleteImmediately.insert(entity); entitiesToDeleteImmediately.insert(entity);
const auto sessionID = DependencyManager::get<NodeList>()->getSessionUUID(); const auto sessionID = DependencyManager::get<NodeList>()->getSessionUUID();
entity->collectChildrenForDelete(entitiesToDeleteImmediately, domainEntities, sessionID); entity->collectChildrenForDelete(entitiesToDeleteImmediately, sessionID);
} }
if (!entitiesToDeleteImmediately.empty()) { if (!entitiesToDeleteImmediately.empty()) {
_entityTree->deleteEntitiesByPointer(entitiesToDeleteImmediately); _entityTree->deleteEntitiesByPointer(entitiesToDeleteImmediately);
@ -1009,10 +1006,6 @@ void EntityScriptingInterface::deleteEntity(const QUuid& id) {
getEntityPacketSender()->getMyAvatar()->clearAvatarEntity(entityID, false); getEntityPacketSender()->getMyAvatar()->clearAvatarEntity(entityID, false);
} }
} }
// finally ask entity-server to delete domainEntities
foreach (auto entity, domainEntities) {
getEntityPacketSender()->queueEraseEntityMessage(entity->getID());
}
} }
QString EntityScriptingInterface::getEntityType(const QUuid& entityID) { QString EntityScriptingInterface::getEntityType(const QUuid& entityID) {

View file

@ -261,14 +261,10 @@ void EntitySimulation::processDeadEntities() {
return; return;
} }
SetOfEntities entitiesToDeleteImmediately; SetOfEntities entitiesToDeleteImmediately;
// NOTE: dummyList will be empty because this base-class implementation is only used server-side
// for which ATM we only process domain-entities, and since we are passing nullSessionID for authorization
// EntityItem::collectChildrenForDelete() will not collect domain-entities into this side list.
SetOfEntities dummyList;
QUuid nullSessionID; QUuid nullSessionID;
foreach (auto entity, _deadEntitiesToRemoveFromTree) { foreach (auto entity, _deadEntitiesToRemoveFromTree) {
entitiesToDeleteImmediately.insert(entity); entitiesToDeleteImmediately.insert(entity);
entity->collectChildrenForDelete(entitiesToDeleteImmediately, dummyList, nullSessionID); entity->collectChildrenForDelete(entitiesToDeleteImmediately, nullSessionID);
} }
if (_entityTree) { if (_entityTree) {
_entityTree->deleteEntitiesByPointer(entitiesToDeleteImmediately); _entityTree->deleteEntitiesByPointer(entitiesToDeleteImmediately);

View file

@ -78,7 +78,7 @@ public:
virtual void prepareEntityForDelete(EntityItemPointer entity); virtual void prepareEntityForDelete(EntityItemPointer entity);
void processChangedEntities(); void processChangedEntities();
virtual void queueEraseDomainEntities(const SetOfEntities& domainEntities) const { } virtual void queueEraseDomainEntity(const QUuid& id) const { }
protected: protected:
virtual void addEntityToInternalLists(EntityItemPointer entity); virtual void addEntityToInternalLists(EntityItemPointer entity);

View file

@ -697,7 +697,6 @@ void EntityTree::deleteEntitiesByID(const QSet<EntityItemID>& ids, bool force, b
}); });
} else { } else {
SetOfEntities entitiesToDelete; SetOfEntities entitiesToDelete;
SetOfEntities domainEntities;
QUuid sessionID = DependencyManager::get<NodeList>()->getSessionUUID(); QUuid sessionID = DependencyManager::get<NodeList>()->getSessionUUID();
withWriteLock([&] { withWriteLock([&] {
for (auto id : ids) { for (auto id : ids) {
@ -708,10 +707,12 @@ void EntityTree::deleteEntitiesByID(const QSet<EntityItemID>& ids, bool force, b
} }
if (entity) { if (entity) {
if (entity->isDomainEntity()) { if (entity->isDomainEntity()) {
domainEntities.insert(entity); if (_simulation) {
_simulation->queueEraseDomainEntity(entity->getID());
}
} else if (entity->isLocalEntity() || entity->isMyAvatarEntity()) { } else if (entity->isLocalEntity() || entity->isMyAvatarEntity()) {
entitiesToDelete.insert(entity); entitiesToDelete.insert(entity);
entity->collectChildrenForDelete(entitiesToDelete, domainEntities, sessionID); entity->collectChildrenForDelete(entitiesToDelete, sessionID);
} }
} }
} }
@ -719,10 +720,6 @@ void EntityTree::deleteEntitiesByID(const QSet<EntityItemID>& ids, bool force, b
deleteEntitiesByPointer(entitiesToDelete); deleteEntitiesByPointer(entitiesToDelete);
} }
}); });
if (!domainEntities.empty() && _simulation) {
// interface-client can't delete domainEntities outright, they must roundtrip through the entity-server
_simulation->queueEraseDomainEntities(domainEntities);
}
} }
} }
@ -2366,7 +2363,6 @@ int EntityTree::processEraseMessage(ReceivedMessage& message, const SharedNodePo
#ifdef EXTRA_ERASE_DEBUGGING #ifdef EXTRA_ERASE_DEBUGGING
qCDebug(entities) << "EntityTree::processEraseMessage()"; qCDebug(entities) << "EntityTree::processEraseMessage()";
#endif #endif
SetOfEntities consequentialDomainEntities;
withWriteLock([&] { withWriteLock([&] {
message.seek(sizeof(OCTREE_PACKET_FLAGS) + sizeof(OCTREE_PACKET_SEQUENCE) + sizeof(OCTREE_PACKET_SENT_TIME)); message.seek(sizeof(OCTREE_PACKET_FLAGS) + sizeof(OCTREE_PACKET_SEQUENCE) + sizeof(OCTREE_PACKET_SENT_TIME));
@ -2413,7 +2409,7 @@ int EntityTree::processEraseMessage(ReceivedMessage& message, const SharedNodePo
SetOfEntities entitiesToDelete; SetOfEntities entitiesToDelete;
for (auto entity : domainEntities) { for (auto entity : domainEntities) {
entitiesToDelete.insert(entity); entitiesToDelete.insert(entity);
entity->collectChildrenForDelete(entitiesToDelete, consequentialDomainEntities, sessionID); entity->collectChildrenForDelete(entitiesToDelete, sessionID);
} }
if (!entitiesToDelete.empty()) { if (!entitiesToDelete.empty()) {
@ -2421,9 +2417,6 @@ int EntityTree::processEraseMessage(ReceivedMessage& message, const SharedNodePo
} }
} }
}); });
if (!consequentialDomainEntities.empty() && _simulation) {
_simulation->queueEraseDomainEntities(consequentialDomainEntities);
}
return message.getPosition(); return message.getPosition();
} }

View file

@ -176,7 +176,6 @@ void PhysicalEntitySimulation::processDeadEntities() {
} }
PROFILE_RANGE(simulation_physics, "Deletes"); PROFILE_RANGE(simulation_physics, "Deletes");
SetOfEntities entitiesToDeleteImmediately; SetOfEntities entitiesToDeleteImmediately;
SetOfEntities domainEntities;
QUuid sessionID = Physics::getSessionUUID(); QUuid sessionID = Physics::getSessionUUID();
QMutexLocker lock(&_mutex); QMutexLocker lock(&_mutex);
for (auto entity : _deadEntitiesToRemoveFromTree) { for (auto entity : _deadEntitiesToRemoveFromTree) {
@ -185,18 +184,15 @@ void PhysicalEntitySimulation::processDeadEntities() {
_entitiesToRemoveFromPhysics.insert(entity); _entitiesToRemoveFromPhysics.insert(entity);
} }
if (entity->isDomainEntity()) { if (entity->isDomainEntity()) {
domainEntities.insert(entity); // interface-client can't delete domainEntities outright, they must roundtrip through the entity-server
_entityPacketSender->queueEraseEntityMessage(entity->getID());
} else if (entity->isLocalEntity() || entity->isMyAvatarEntity()) { } else if (entity->isLocalEntity() || entity->isMyAvatarEntity()) {
entitiesToDeleteImmediately.insert(entity); entitiesToDeleteImmediately.insert(entity);
entity->collectChildrenForDelete(entitiesToDeleteImmediately, domainEntities, sessionID); entity->collectChildrenForDelete(entitiesToDeleteImmediately, sessionID);
} }
} }
_deadEntitiesToRemoveFromTree.clear(); _deadEntitiesToRemoveFromTree.clear();
// interface-client can't delete domainEntities outright, they must roundtrip through the entity-server
for (auto entity : domainEntities) {
_entityPacketSender->queueEraseEntityMessage(entity->getID());
}
if (!entitiesToDeleteImmediately.empty()) { if (!entitiesToDeleteImmediately.empty()) {
getEntityTree()->deleteEntitiesByPointer(entitiesToDeleteImmediately); getEntityTree()->deleteEntitiesByPointer(entitiesToDeleteImmediately);
} }
@ -233,12 +229,9 @@ void PhysicalEntitySimulation::clearEntities() {
EntitySimulation::clearEntities(); EntitySimulation::clearEntities();
} }
void PhysicalEntitySimulation::queueEraseDomainEntities(const SetOfEntities& domainEntities) const { void PhysicalEntitySimulation::queueEraseDomainEntity(const QUuid& id) const {
if (_entityPacketSender) { if (_entityPacketSender) {
for (auto domainEntity : domainEntities) { _entityPacketSender->queueEraseEntityMessage(id);
assert(domainEntity->isDomainEntity());
_entityPacketSender->queueEraseEntityMessage(domainEntity->getID());
}
} }
} }

View file

@ -66,7 +66,7 @@ public:
void takeDeadAvatarEntities(SetOfEntities& deadEntities); void takeDeadAvatarEntities(SetOfEntities& deadEntities);
virtual void clearEntities() override; virtual void clearEntities() override;
void queueEraseDomainEntities(const SetOfEntities& domainEntities) const override; void queueEraseDomainEntity(const QUuid& id) const override;
signals: signals:
void entityCollisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const Collision& collision); void entityCollisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const Collision& collision);