diff --git a/assignment-client/src/entities/EntityServer.cpp b/assignment-client/src/entities/EntityServer.cpp index e56adfd16a..4c4fcbf2dd 100644 --- a/assignment-client/src/entities/EntityServer.cpp +++ b/assignment-client/src/entities/EntityServer.cpp @@ -370,14 +370,18 @@ void EntityServer::entityFilterAdded(EntityItemID id, bool success) { void EntityServer::nodeAdded(SharedNodePointer node) { EntityTreePointer tree = std::static_pointer_cast(_tree); - tree->knowAvatarID(node->getUUID()); + if (tree) { + tree->knowAvatarID(node->getUUID()); + } OctreeServer::nodeAdded(node); } void EntityServer::nodeKilled(SharedNodePointer node) { EntityTreePointer tree = std::static_pointer_cast(_tree); - tree->deleteDescendantsOfAvatar(node->getUUID()); - tree->forgetAvatarID(node->getUUID()); + if (tree) { + tree->deleteDescendantsOfAvatar(node->getUUID()); + tree->forgetAvatarID(node->getUUID()); + } OctreeServer::nodeKilled(node); } diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index a22f34a874..419f039e8c 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -2212,16 +2212,24 @@ void EntityTree::fixupNeedsParentFixups() { } entity->postParentFixup(); - } else if (getIsServer() || _avatarIDs.contains(entity->getParentID())) { - std::lock_guard lock(_childrenOfAvatarsLock); - // this is a child of an avatar, which the entity server will never have - // a SpatiallyNestable object for. Add it to a list for cleanup when the avatar leaves. - if (!_childrenOfAvatars.contains(entity->getParentID())) { - _childrenOfAvatars[entity->getParentID()] = QSet(); + } else { + bool needsUpdate = getIsServer(); + if (!needsUpdate) { + std::lock_guard lock(_avatarIDsLock); + needsUpdate = _avatarIDs.contains(entity->getParentID()); + } + + if (needsUpdate) { + std::lock_guard lock(_childrenOfAvatarsLock); + // this is a child of an avatar, which the entity server will never have + // a SpatiallyNestable object for. Add it to a list for cleanup when the avatar leaves. + if (!_childrenOfAvatars.contains(entity->getParentID())) { + _childrenOfAvatars[entity->getParentID()] = QSet(); + } + _childrenOfAvatars[entity->getParentID()] += entity->getEntityItemID(); + doMove = true; + iter.remove(); // and pull it out of the list } - _childrenOfAvatars[entity->getParentID()] += entity->getEntityItemID(); - doMove = true; - iter.remove(); // and pull it out of the list } if (queryAACubeSuccess && doMove) { @@ -2241,9 +2249,19 @@ void EntityTree::fixupNeedsParentFixups() { } } -void EntityTree::deleteDescendantsOfAvatar(QUuid avatarID) { +void EntityTree::knowAvatarID(const QUuid& avatarID) { + std::lock_guard lock(_avatarIDsLock); + _avatarIDs += avatarID; +} + +void EntityTree::forgetAvatarID(const QUuid& avatarID) { + std::lock_guard lock(_avatarIDsLock); + _avatarIDs -= avatarID; +} + +void EntityTree::deleteDescendantsOfAvatar(const QUuid& avatarID) { std::lock_guard lock(_childrenOfAvatarsLock); - QHash>::const_iterator itr = _childrenOfAvatars.constFind(avatarID); + auto itr = _childrenOfAvatars.find(avatarID); if (itr != _childrenOfAvatars.end()) { if (!itr.value().empty()) { std::vector ids; diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index 85f2310edb..4ee0a7dca4 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -239,9 +239,9 @@ public: Q_INVOKABLE int getJointIndex(const QUuid& entityID, const QString& name) const; Q_INVOKABLE QStringList getJointNames(const QUuid& entityID) const; - void knowAvatarID(QUuid avatarID) { _avatarIDs += avatarID; } - void forgetAvatarID(QUuid avatarID) { _avatarIDs -= avatarID; } - void deleteDescendantsOfAvatar(QUuid avatarID); + void knowAvatarID(const QUuid& avatarID); + void forgetAvatarID(const QUuid& avatarID); + void deleteDescendantsOfAvatar(const QUuid& avatarID); void removeFromChildrenOfAvatars(EntityItemPointer entity); void addToNeedsParentFixupList(EntityItemPointer entity); @@ -364,6 +364,7 @@ protected: QVector _needsParentFixup; // entites with a parentID but no (yet) known parent instance mutable QReadWriteLock _needsParentFixupLock; + std::mutex _avatarIDsLock; // we maintain a list of avatarIDs to notice when an entity is a child of one. QSet _avatarIDs; // IDs of avatars connected to entity server std::mutex _childrenOfAvatarsLock;